Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2141d52a7a | ||
|
|
4c84235064 | ||
|
|
0e194a5408 | ||
|
|
4b60eac330 | ||
|
|
cb017c359d | ||
|
|
15aaaa5c14 | ||
|
|
290bee83b4 | ||
|
|
fcd2461205 | ||
|
|
52198d0249 | ||
|
|
ba7ccfdfa0 | ||
|
|
92d3b086fa | ||
|
|
e180595dcd | ||
|
|
ed708bdde0 | ||
|
|
d7852d640f | ||
|
|
a2fdee88b6 | ||
|
|
af070b1578 | ||
|
|
83a8eeef0f | ||
|
|
34f8e7402b | ||
|
|
1b7e2cd850 | ||
|
|
463b7f0fc9 | ||
|
|
266495abc8 | ||
|
|
453d4365d3 | ||
|
|
e0ce6275bf | ||
|
|
16b16ce6c6 | ||
|
|
80c72a274e | ||
|
|
91f0f7954c | ||
|
|
c74abcb608 | ||
|
|
da8b91594e | ||
|
|
fc26f5a73e | ||
|
|
4f60766d5d | ||
|
|
e992aeebef | ||
|
|
4108346a98 | ||
|
|
946fadadc2 | ||
|
|
d2cc2833a9 | ||
|
|
af57326194 | ||
|
|
98c69e9e17 | ||
|
|
395edd0563 | ||
|
|
43e87e7786 | ||
|
|
ad347504c6 | ||
|
|
4e6e99b695 | ||
|
|
104624a322 | ||
|
|
79d166e6af | ||
|
|
86c934e8ac | ||
|
|
a034cbf30e | ||
|
|
d5680ebf8a | ||
|
|
53f2fcc945 | ||
|
|
612e127be4 | ||
|
|
2b0d975cee | ||
|
|
248ab9bb6b | ||
|
|
314ce85410 | ||
|
|
9ff45dbcc2 | ||
|
|
6caf19bc99 | ||
|
|
c2b04d0977 | ||
|
|
9012c4a558 | ||
|
|
65a84937f2 | ||
|
|
eebb88b6b1 | ||
|
|
06ab7c5116 | ||
|
|
89f03c7601 | ||
|
|
9d2eb14c0c | ||
|
|
7b3cb54983 | ||
|
|
a09bad2fed | ||
|
|
afd897edfe | ||
|
|
efc79cb6e7 | ||
|
|
35efe39ea7 | ||
|
|
034067bd6e | ||
|
|
0d75cd5d15 |
@@ -27,3 +27,4 @@ fourseven:scss@2.1.1
|
|||||||
wolves:bourbon
|
wolves:bourbon
|
||||||
meteorhacks:subs-manager
|
meteorhacks:subs-manager
|
||||||
meteorhacks:kadira
|
meteorhacks:kadira
|
||||||
|
chuangbo:marked
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ blaze-tools@1.0.3
|
|||||||
boilerplate-generator@1.0.3
|
boilerplate-generator@1.0.3
|
||||||
callback-hook@1.0.3
|
callback-hook@1.0.3
|
||||||
check@1.0.5
|
check@1.0.5
|
||||||
|
chuangbo:marked@0.3.5
|
||||||
coffeescript@1.0.6
|
coffeescript@1.0.6
|
||||||
dburles:collection-helpers@1.0.3
|
dburles:collection-helpers@1.0.3
|
||||||
dburles:mongo-collection-instances@0.3.3
|
dburles:mongo-collection-instances@0.3.3
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ Characters = new Mongo.Collection("characters");
|
|||||||
|
|
||||||
Schemas.Character = new SimpleSchema({
|
Schemas.Character = new SimpleSchema({
|
||||||
//strings
|
//strings
|
||||||
name: {type: String, defaultValue: "", trim: false},
|
name: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
alignment: {type: String, defaultValue: "", trim: false},
|
alignment: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
gender: {type: String, defaultValue: "", trim: false},
|
gender: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
race: {type: String, defaultValue: "", trim: false},
|
race: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
description: {type: String, defaultValue: "", trim: false},
|
picture: {type: String, defaultValue: "", trim: true, optional: true},
|
||||||
personality: {type: String, defaultValue: "", trim: false},
|
description: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
ideals: {type: String, defaultValue: "", trim: false},
|
personality: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
bonds: {type: String, defaultValue: "", trim: false},
|
ideals: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
flaws: {type: String, defaultValue: "", trim: false},
|
bonds: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
backstory: {type: String, defaultValue: "", trim: false},
|
flaws: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
|
backstory: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
|
|
||||||
//attributes
|
//attributes
|
||||||
//ability scores
|
//ability scores
|
||||||
@@ -176,99 +177,115 @@ Schemas.Character = new SimpleSchema({
|
|||||||
"settings.useStandardEncumbrance": {type: Boolean, defaultValue: true},
|
"settings.useStandardEncumbrance": {type: Boolean, defaultValue: true},
|
||||||
//hide spellcasting
|
//hide spellcasting
|
||||||
"settings.hideSpellcasting": {type: Boolean, defaultValue: false},
|
"settings.hideSpellcasting": {type: Boolean, defaultValue: false},
|
||||||
|
//show to anyone with link
|
||||||
|
"settings.viewPermission": {
|
||||||
|
type: String,
|
||||||
|
defaultValue: "whitelist",
|
||||||
|
allowedValues: ["whitelist", "public"],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Characters.attachSchema(Schemas.Character);
|
Characters.attachSchema(Schemas.Character);
|
||||||
|
|
||||||
var attributeBase = function(charId, statName){
|
var attributeBase = preventLoop(function(charId, statName){
|
||||||
check(statName, String);
|
check(statName, String);
|
||||||
//if it's a damage multiplier, we treat it specially
|
//if it's a damage multiplier, we treat it specially
|
||||||
if (_.contains(DAMAGE_MULTIPLIERS, statName)){
|
if (_.contains(DAMAGE_MULTIPLIERS, statName)){
|
||||||
var effects = Effects.find(
|
var invulnerabilityCount = Effects.find({
|
||||||
{charId: charId, stat: statName, enabled: true, operation: "mul"}
|
charId: charId,
|
||||||
).fetch();
|
stat: statName,
|
||||||
var resistCount = 0;
|
enabled: true,
|
||||||
var vulnCount = 0;
|
operation: "mul",
|
||||||
var multiplierEvaluationFail = false;
|
value: 0,
|
||||||
_.each(effects, function(effect){
|
}).count();
|
||||||
var val = evaluateEffect(charId, effect);
|
if (invulnerabilityCount) return 0;
|
||||||
if (val === 0.5){ //resistance
|
var resistCount = Effects.find({
|
||||||
resistCount += 1;
|
charId: charId,
|
||||||
} else if (val === 2){ //vulnerability
|
stat: statName,
|
||||||
vulnCount += 1;
|
enabled: true,
|
||||||
} else if (val === 0){ //imunity
|
operation: "mul",
|
||||||
return 0; //imunity is absolute
|
value: 0.5,
|
||||||
} else {
|
}).count();
|
||||||
multiplierEvaluationFail = true;
|
var vulnCount = Effects.find({
|
||||||
}
|
charId: charId,
|
||||||
});
|
stat: statName,
|
||||||
if (multiplierEvaluationFail){
|
enabled: true,
|
||||||
//we can't work it out correctly, set the value to 1
|
operation: "mul",
|
||||||
//and try work it out using regular maths below
|
value: 2,
|
||||||
value = 1;
|
}).count();
|
||||||
} else if (resistCount && !vulnCount){
|
if (!resistCount && !vulnCount){
|
||||||
|
return 1;
|
||||||
|
} else if (resistCount && !vulnCount){
|
||||||
return 0.5;
|
return 0.5;
|
||||||
} else if (!resistCount && vulnCount){
|
} else if (!resistCount && vulnCount){
|
||||||
return 2;
|
return 2;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var value;
|
||||||
|
var base = 0;
|
||||||
|
var add = 0;
|
||||||
|
var mul = 1;
|
||||||
|
var min = Number.NEGATIVE_INFINITY;
|
||||||
|
var max = Number.POSITIVE_INFINITY;
|
||||||
|
|
||||||
var value = 0;
|
Effects.find({
|
||||||
|
charId: charId,
|
||||||
//start with the highest base value
|
stat: statName,
|
||||||
Effects.find(
|
enabled: true,
|
||||||
{charId: charId, stat: statName, enabled: true, operation: "base"}
|
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||||
).forEach(function(effect){
|
}).forEach(function(effect) {
|
||||||
var efv = evaluateEffect(charId, effect);
|
value = evaluateEffect(charId, effect);
|
||||||
if (efv > value){
|
if (effect.operation === "base"){
|
||||||
value = efv;
|
if (value > base) base = value;
|
||||||
|
} else if (effect.operation === "add"){
|
||||||
|
add += value;
|
||||||
|
} else if (effect.operation === "mul"){
|
||||||
|
mul *= value;
|
||||||
|
} else if (effect.operation === "min"){
|
||||||
|
if (value > min) min = value;
|
||||||
|
} else if (effect.operation === "max"){
|
||||||
|
if (value < max) max = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//add all the add values
|
var result = (base + add) * mul;
|
||||||
Effects.find(
|
if (result < min) result = min;
|
||||||
{charId: charId, stat: statName, enabled: true, operation: "add"}
|
if (result > max) result = max;
|
||||||
).forEach(function(effect){
|
|
||||||
value += evaluateEffect(charId, effect);
|
|
||||||
});
|
|
||||||
|
|
||||||
//multiply all the mul values
|
return Math.floor(result);
|
||||||
Effects.find(
|
});
|
||||||
{charId: charId, stat: statName, enabled: true, operation: "mul"}
|
|
||||||
).forEach(function(effect){
|
|
||||||
value *= evaluateEffect(charId, effect);
|
|
||||||
});
|
|
||||||
|
|
||||||
//ensure value is >= all mins
|
if (Meteor.isClient) {
|
||||||
Effects.find(
|
Template.registerHelper("characterCalculate", function(func, charId, input) {
|
||||||
{charId: charId, stat: statName, enabled: true, operation: "min"}
|
try {
|
||||||
).forEach(function(effect){
|
return Characters.calculate[func](charId, input);
|
||||||
var min = evaluateEffect(charId, effect);
|
} catch (e){
|
||||||
value = value > min ? value : min;
|
if (!Characters.calculate[func]){
|
||||||
|
throw new Error(func + "is not a function name");
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//ensure value is <= all maxes
|
//create a local memoize with a argument concatenating hash function
|
||||||
Effects.find(
|
var memoize = function(f) {
|
||||||
{charId: charId, stat: statName, enabled: true, operation: "max"}
|
return Tracker.memoize(f, function() {
|
||||||
).forEach(function(effect){
|
return _.reduce(arguments, function(memo, arg) {
|
||||||
var max = evaluateEffect(charId, effect);
|
return memo + arg;
|
||||||
value = value < max ? value : max;
|
}, "");
|
||||||
});
|
});
|
||||||
return value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//functions and calculated values.
|
//memoize funcitons that have finds and slow loops
|
||||||
//These functions can only rely on this._id since no other
|
Characters.calculate = {
|
||||||
//field is likely to be attached to all returned characters
|
getField: function(charId, fieldName) {
|
||||||
Characters.helpers({
|
|
||||||
//returns the value stored in the field requested
|
|
||||||
//will set up dependencies on just that field
|
|
||||||
getField : function(fieldName){
|
|
||||||
var fieldSelector = {};
|
var fieldSelector = {};
|
||||||
fieldSelector[fieldName] = 1;
|
fieldSelector[fieldName] = 1;
|
||||||
var char = Characters.findOne(this._id, {fields: fieldSelector});
|
var char = Characters.findOne(charId, {fields: fieldSelector});
|
||||||
var field = char[fieldName];
|
var field = char[fieldName];
|
||||||
if (field === undefined){
|
if (field === undefined){
|
||||||
throw new Meteor.Error(
|
throw new Meteor.Error(
|
||||||
@@ -281,8 +298,7 @@ Characters.helpers({
|
|||||||
}
|
}
|
||||||
return field;
|
return field;
|
||||||
},
|
},
|
||||||
//returns the value of a field
|
fieldValue: function(charId, fieldName) {
|
||||||
fieldValue : function(fieldName){
|
|
||||||
if (!Schemas.Character.schema(fieldName)){
|
if (!Schemas.Character.schema(fieldName)){
|
||||||
throw new Meteor.Error(
|
throw new Meteor.Error(
|
||||||
"Field not found",
|
"Field not found",
|
||||||
@@ -292,102 +308,92 @@ Characters.helpers({
|
|||||||
//duck typing to get the right value function
|
//duck typing to get the right value function
|
||||||
//.ability implies skill
|
//.ability implies skill
|
||||||
if (Schemas.Character.schema(fieldName + ".ability")){
|
if (Schemas.Character.schema(fieldName + ".ability")){
|
||||||
return this.skillMod(fieldName);
|
return Characters.calculate.skillMod(charId, fieldName);
|
||||||
}
|
}
|
||||||
//adjustment implies attribute
|
//adjustment implies attribute
|
||||||
if (Schemas.Character.schema(fieldName + ".adjustment")){
|
if (Schemas.Character.schema(fieldName + ".adjustment")){
|
||||||
return this.attributeValue(fieldName);
|
return Characters.calculate.attributeValue(charId, fieldName);
|
||||||
}
|
}
|
||||||
//fall back to just returning the field itself
|
//fall back to just returning the field itself
|
||||||
return this.getField(fieldName);
|
return Characters.calculate.getField(charId, fieldName);
|
||||||
},
|
},
|
||||||
|
attributeValue: memoize(function(charId, attributeName){
|
||||||
attributeValue: function(attributeName){
|
var attribute = Characters.calculate.getField(charId, attributeName);
|
||||||
var charId = this._id;
|
|
||||||
var attribute = this.getField(attributeName);
|
|
||||||
//base value
|
//base value
|
||||||
var value = this.attributeBase(attributeName);
|
var value = Characters.calculate.attributeBase(charId, attributeName);
|
||||||
//plus adjustment
|
//plus adjustment
|
||||||
value += attribute.adjustment;
|
value += attribute.adjustment;
|
||||||
return value;
|
return value;
|
||||||
},
|
}),
|
||||||
|
attributeBase: memoize(function(charId, attributeName){
|
||||||
attributeBase: preventLoop(function(attributeName){
|
|
||||||
var charId = this._id;
|
|
||||||
//base value
|
|
||||||
return attributeBase(charId, attributeName);
|
return attributeBase(charId, attributeName);
|
||||||
}),
|
}),
|
||||||
|
skillMod: memoize(preventLoop(function(charId, skillName){
|
||||||
skillMod: preventLoop(function(skillName){
|
var skill = Characters.calculate.getField(charId, skillName);
|
||||||
var charId = this._id;
|
|
||||||
var skill = this.getField(skillName);
|
|
||||||
//get the final value of the ability score
|
//get the final value of the ability score
|
||||||
var ability = this.attributeValue(skill.ability);
|
var ability = Characters.calculate.attributeValue(charId, skill.ability);
|
||||||
|
|
||||||
//base modifier
|
//base modifier
|
||||||
var mod = +getMod(ability);
|
var mod = +getMod(ability);
|
||||||
|
|
||||||
//multiply proficiency bonus by largest value in proficiency array
|
//multiply proficiency bonus by largest value in proficiency array
|
||||||
var prof = this.proficiency(skillName);
|
var prof = Characters.calculate.proficiency(charId, skillName);
|
||||||
|
|
||||||
//add multiplied proficiency bonus to modifier
|
//add multiplied proficiency bonus to modifier
|
||||||
mod += prof * this.attributeValue("proficiencyBonus");
|
mod += prof * Characters.calculate.attributeValue(charId, "proficiencyBonus");
|
||||||
|
|
||||||
//apply all effects
|
//apply all effects
|
||||||
var rawEffects = Effects.find(
|
var value;
|
||||||
{charId: charId, stat: skillName, enabled: true}
|
var add = 0;
|
||||||
).fetch();
|
var mul = 1;
|
||||||
var effects = _.groupBy(rawEffects, "operation");
|
var min = Number.NEGATIVE_INFINITY;
|
||||||
_.forEach(effects.add, function(effect){
|
var max = Number.POSITIVE_INFINITY;
|
||||||
mod += evaluateEffect(charId, effect);
|
|
||||||
});
|
|
||||||
_.forEach(effects.mul, function(effect){
|
|
||||||
mod *= evaluateEffect(charId, effect);
|
|
||||||
});
|
|
||||||
_.forEach(effects.min, function(effect){
|
|
||||||
var min = evaluateEffect(charId, effect);
|
|
||||||
mod = mod > min ? mod : min;
|
|
||||||
});
|
|
||||||
_.forEach(effects.max, function(effect){
|
|
||||||
var max = evaluateEffect(charId, effect);
|
|
||||||
mod = mod < max ? mod : max;
|
|
||||||
});
|
|
||||||
return signedString(mod);
|
|
||||||
}),
|
|
||||||
|
|
||||||
proficiency: function(skillName){
|
Effects.find({
|
||||||
var charId = this._id;
|
charId: charId,
|
||||||
//return largest value in proficiency array
|
stat: skillName,
|
||||||
var prof = 0;
|
enabled: true,
|
||||||
Proficiencies.find(
|
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||||
{charId: charId, name: skillName, enabled: true}
|
}).forEach(function(effect) {
|
||||||
).forEach(function(proficiency){
|
value = evaluateEffect(charId, effect);
|
||||||
var newProf = proficiency.value;
|
if (effect.operation === "add"){
|
||||||
if (newProf > prof){
|
add += value;
|
||||||
prof = newProf;
|
} else if (effect.operation === "mul"){
|
||||||
|
mul *= value;
|
||||||
|
} else if (effect.operation === "min"){
|
||||||
|
if (value > min) min = value;
|
||||||
|
} else if (effect.operation === "max"){
|
||||||
|
if (value < max) max = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return prof;
|
var result = (mod + add) * mul;
|
||||||
},
|
if (result < min) result = min;
|
||||||
|
if (result > max) result = max;
|
||||||
|
|
||||||
passiveSkill: function(skillName){
|
return Math.floor(result);
|
||||||
if (_.isString(skillName)){
|
})),
|
||||||
var skill = this.getField(skillName);
|
proficiency: memoize(function(charId, skillName){
|
||||||
}
|
//return largest value in proficiency array
|
||||||
var charId = this._id;
|
var prof = Proficiencies.findOne(
|
||||||
var mod = +this.skillMod(skillName);
|
{charId: charId, name: skillName, enabled: true},
|
||||||
|
{sort: {value: -1}}
|
||||||
|
);
|
||||||
|
return prof && prof.value || 0;
|
||||||
|
}),
|
||||||
|
passiveSkill: memoize(function(charId, skillName){
|
||||||
|
var skill = Characters.calculate.getField(charId, skillName);
|
||||||
|
var mod = +Characters.calculate.skillMod(charId, skillName);
|
||||||
var value = 10 + mod;
|
var value = 10 + mod;
|
||||||
Effects.find(
|
Effects.find(
|
||||||
{charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"}
|
{charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"}
|
||||||
).forEach(function(effect){
|
).forEach(function(effect){
|
||||||
value += evaluateEffect(charId, effect);
|
value += evaluateEffect(charId, effect);
|
||||||
});
|
});
|
||||||
return value;
|
var advantage = Characters.calculate.advantage(charId, skillName);
|
||||||
//TODO decide whether (dis)advantage gives (-)+5 to passive checks
|
value += 5 * advantage;
|
||||||
},
|
return Math.floor(value);
|
||||||
|
}),
|
||||||
advantage: function(skillName){
|
advantage: memoize(function(charId, skillName){
|
||||||
var charId = this._id;
|
|
||||||
var advantage = Effects.find(
|
var advantage = Effects.find(
|
||||||
{charId: charId, stat: skillName, enabled: true, operation: "advantage"}
|
{charId: charId, stat: skillName, enabled: true, operation: "advantage"}
|
||||||
).count();
|
).count();
|
||||||
@@ -397,19 +403,18 @@ Characters.helpers({
|
|||||||
if (advantage && !disadvantage) return 1;
|
if (advantage && !disadvantage) return 1;
|
||||||
if (disadvantage && !advantage) return -1;
|
if (disadvantage && !advantage) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
}),
|
||||||
|
abilityMod: function(charId, attribute){
|
||||||
|
return getMod(
|
||||||
|
Characters.calculate.attributeValue(charId, attribute)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
passiveAbility: function(charId, attribute){
|
||||||
abilityMod: function(attribute){
|
var mod = +getMod(Characters.calculate.attributeValue(charId, attribute));
|
||||||
return signedString(getMod(this.attributeValue(attribute)));
|
|
||||||
},
|
|
||||||
|
|
||||||
passiveAbility: function(attribute){
|
|
||||||
var mod = +getMod(this.attributeValue(attribute));
|
|
||||||
return 10 + mod;
|
return 10 + mod;
|
||||||
},
|
},
|
||||||
|
xpLevel: function(charId){
|
||||||
xpLevel: function(){
|
var xp = Characters.calculate.experience(charId);
|
||||||
var xp = this.experience();
|
|
||||||
for (var i = 0; i < 19; i++){
|
for (var i = 0; i < 19; i++){
|
||||||
if (xp < XP_TABLE[i]){
|
if (xp < XP_TABLE[i]){
|
||||||
return i;
|
return i;
|
||||||
@@ -418,30 +423,103 @@ Characters.helpers({
|
|||||||
if (xp > 355000) return 20;
|
if (xp > 355000) return 20;
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
|
level: memoize(function(charId){
|
||||||
level: function(){
|
|
||||||
var level = 0;
|
var level = 0;
|
||||||
Classes.find({charId: this._id}).forEach(function(cls){
|
Classes.find({charId: charId}).forEach(function(cls){
|
||||||
level += cls.level;
|
level += cls.level;
|
||||||
});
|
});
|
||||||
return level;
|
return level;
|
||||||
},
|
}),
|
||||||
|
experience: memoize(function(charId){
|
||||||
experience: function(){
|
|
||||||
var xp = 0;
|
var xp = 0;
|
||||||
Experiences.find(
|
Experiences.find(
|
||||||
{charId: this._id},
|
{charId: charId},
|
||||||
{fields: {value: 1}}
|
{fields: {value: 1}}
|
||||||
).forEach(function(e){
|
).forEach(function(e){
|
||||||
xp += e.value;
|
xp += e.value;
|
||||||
});
|
});
|
||||||
return xp;
|
return xp;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
var depreciated = function() {
|
||||||
|
//var err = new Error("this function has been depreciated");
|
||||||
|
var name = "";
|
||||||
|
if (Template.instance()){
|
||||||
|
name = Template.instance().view.name;
|
||||||
|
}
|
||||||
|
var logString = "this function has been depreciated \n";
|
||||||
|
if (name){
|
||||||
|
logString += "View: " + name + "\n\n";
|
||||||
|
}
|
||||||
|
//logString += err.stack + "\n\n---------------------\n\n";
|
||||||
|
console.log(logString);
|
||||||
|
};
|
||||||
|
|
||||||
|
//functions and calculated values.
|
||||||
|
//These functions can only rely on this._id since no other
|
||||||
|
//field is likely to be attached to all returned characters
|
||||||
|
Characters.helpers({
|
||||||
|
//returns the value stored in the field requested
|
||||||
|
//will set up dependencies on just that field
|
||||||
|
getField : function(fieldName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.getField(this._id, fieldName);
|
||||||
|
},
|
||||||
|
//returns the value of a field
|
||||||
|
fieldValue : function(fieldName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.fieldValue(this._id, fieldName);
|
||||||
|
},
|
||||||
|
attributeValue: function(attributeName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.attributeValue(this._id, attributeName);
|
||||||
|
},
|
||||||
|
attributeBase: function(attributeName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.attributeBase(this._id, attributeName);
|
||||||
|
},
|
||||||
|
skillMod: function(skillName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.skillMod(this._id, skillName);
|
||||||
|
},
|
||||||
|
proficiency: function(skillName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.proficiency(this._id, skillName);
|
||||||
|
},
|
||||||
|
passiveSkill: function(skillName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.passiveSkill(this._id, skillName);
|
||||||
|
},
|
||||||
|
advantage: function(skillName){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.advantage(this._id, skillName);
|
||||||
|
},
|
||||||
|
abilityMod: function(attribute){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.abilityMod(this._id, attribute);
|
||||||
|
},
|
||||||
|
passiveAbility: function(attribute){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.passiveAbility(this._id, attribute);
|
||||||
|
},
|
||||||
|
xpLevel: function(){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.xpLevel(this._id);
|
||||||
|
},
|
||||||
|
level: function(){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.level(this._id);
|
||||||
|
},
|
||||||
|
experience: function(){
|
||||||
|
depreciated();
|
||||||
|
return Characters.calculate.experience(this._id);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//clean up all data related to that character before removing it
|
//clean up all data related to that character before removing it
|
||||||
Characters.after.remove(function(userId, character) {
|
if (Meteor.isServer){
|
||||||
if (Meteor.isServer){
|
Characters.after.remove(function(userId, character) {
|
||||||
Actions .remove({charId: character._id});
|
Actions .remove({charId: character._id});
|
||||||
Attacks .remove({charId: character._id});
|
Attacks .remove({charId: character._id});
|
||||||
Buffs .remove({charId: character._id});
|
Buffs .remove({charId: character._id});
|
||||||
@@ -454,8 +532,8 @@ Characters.after.remove(function(userId, character) {
|
|||||||
SpellLists .remove({charId: character._id});
|
SpellLists .remove({charId: character._id});
|
||||||
Items .remove({charId: character._id});
|
Items .remove({charId: character._id});
|
||||||
Containers .remove({charId: character._id});
|
Containers .remove({charId: character._id});
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
Characters.allow({
|
Characters.allow({
|
||||||
insert: function(userId, doc) {
|
insert: function(userId, doc) {
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ Spells.attachSchema(Schemas.Spell);
|
|||||||
|
|
||||||
Spells.attachBehaviour("softRemovable");
|
Spells.attachBehaviour("softRemovable");
|
||||||
makeChild(Spells); //children of spell lists
|
makeChild(Spells); //children of spell lists
|
||||||
|
makeParent(Spells, ["name", "enabled"]); //parents of attacks
|
||||||
|
|
||||||
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||||
Spells.deny(CHARACTER_SUBSCHEMA_DENY);
|
Spells.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||||
|
|||||||
@@ -3,10 +3,6 @@
|
|||||||
* Damage, healing and resource cost/recovery are all adjustments
|
* Damage, healing and resource cost/recovery are all adjustments
|
||||||
*/
|
*/
|
||||||
Schemas.Adjustment = new SimpleSchema({
|
Schemas.Adjustment = new SimpleSchema({
|
||||||
name: {
|
|
||||||
type: String,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
//which stat the adjustment is applied to
|
//which stat the adjustment is applied to
|
||||||
stat: {
|
stat: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Schemas.TemporaryHitPoints = new SimpleSchema({
|
|||||||
name: {type: String, optional: true},
|
name: {type: String, optional: true},
|
||||||
maximum: {type: Number, defaultValue: 0},
|
maximum: {type: Number, defaultValue: 0},
|
||||||
used: {type: Number, defaultValue: 0},
|
used: {type: Number, defaultValue: 0},
|
||||||
deleteOnZero:{type: Boolean, defaultValue: true},
|
deleteOnZero:{type: Boolean, defaultValue: false},
|
||||||
dateAdded: {
|
dateAdded: {
|
||||||
type: Date,
|
type: Date,
|
||||||
autoValue: function() {
|
autoValue: function() {
|
||||||
|
|||||||
@@ -45,12 +45,25 @@ Meteor.methods({
|
|||||||
metaData: Object,
|
metaData: Object,
|
||||||
});
|
});
|
||||||
report.owner = this.userId;
|
report.owner = this.userId;
|
||||||
Reports.insert(report);
|
var id = Reports.insert(report);
|
||||||
|
var user = Meteor.users.findOne(this.userId);
|
||||||
|
var sender = user &&
|
||||||
|
user.emails &&
|
||||||
|
user.emails[0] &&
|
||||||
|
user.emails[0].address ||
|
||||||
|
user.services &&
|
||||||
|
user.services.google &&
|
||||||
|
user.services.google.email ||
|
||||||
|
"reports@dicecloud.com";
|
||||||
|
var bodyText = "Report ID: " + id +
|
||||||
|
"\nSeverity: " + report.severity +
|
||||||
|
"\nType: " + report.type +
|
||||||
|
"\n\n" + report.description;
|
||||||
Email.send({
|
Email.send({
|
||||||
from: "reports@dicecloud.com",
|
from: sender,
|
||||||
to: "stefan.zermatten@gmail.com",
|
to: "stefan.zermatten@gmail.com",
|
||||||
subject: "DiceCloud feedback - " + report.title,
|
subject: "DiceCloud feedback - " + report.title,
|
||||||
text: JSON.stringify(_.omit(report, "metaData"), null, '\t'),
|
text: bodyText,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteReport: function(id) {
|
deleteReport: function(id) {
|
||||||
|
|||||||
@@ -4,17 +4,9 @@ Router.configure({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Router.plugin("ensureSignedIn", {
|
Router.plugin("ensureSignedIn", {
|
||||||
except: [
|
only: [
|
||||||
"home",
|
"profile",
|
||||||
"atSignIn",
|
"characterList",
|
||||||
"atSignUp",
|
|
||||||
"atForgotPassword",
|
|
||||||
"atResetPwd",
|
|
||||||
"atEnrollAccount",
|
|
||||||
"atVerifyEmail",
|
|
||||||
"atResendVerificationEmail",
|
|
||||||
"loginButtons",
|
|
||||||
"notFound",
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -35,7 +27,7 @@ Router.map(function() {
|
|||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
characters: function(){
|
characters: function(){
|
||||||
return Characters.find({}, {fields: {_id: 1}});
|
return Characters.find({}, {fields: {_id: 1}, sort: {name: 1}});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onAfterAction: function() {
|
onAfterAction: function() {
|
||||||
@@ -93,4 +85,11 @@ Router.map(function() {
|
|||||||
document.title = appName;
|
document.title = appName;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route("/guide", {
|
||||||
|
name: "guide",
|
||||||
|
onAfterAction: function() {
|
||||||
|
document.title = appName;
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
Template.registerHelper("canEditCharacter", function(charId) {
|
Template.registerHelper("canEditCharacter", function(charId) {
|
||||||
|
return canEditCharacter(charId);
|
||||||
|
});
|
||||||
|
|
||||||
|
canEditCharacter = function(charId) {
|
||||||
var char = Characters.findOne(charId)
|
var char = Characters.findOne(charId)
|
||||||
var userId = Meteor.userId();
|
var userId = Meteor.userId();
|
||||||
return char.owner === userId ||
|
return char.owner === userId ||
|
||||||
_.contains(char.writers, userId);
|
_.contains(char.writers, userId);
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ openParentDialog = function(parent, charId, heroId) {
|
|||||||
template: "itemDialog",
|
template: "itemDialog",
|
||||||
data: {itemId: parent.id},
|
data: {itemId: parent.id},
|
||||||
};
|
};
|
||||||
|
} else if (parent.collection === "Spells") {
|
||||||
|
detail = {
|
||||||
|
template: "spellDialog",
|
||||||
|
data: {spellId: parent.id},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
detail.heroId = heroId;
|
detail.heroId = heroId;
|
||||||
detail.charId = charId;
|
detail.charId = charId;
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
Template.registerHelper("valueString", function(value) {
|
Template.registerHelper("valueString", function(value) {
|
||||||
|
var intValue = Math.round(value * 100);
|
||||||
|
var cp = intValue % 10;
|
||||||
|
intValue -= cp;
|
||||||
|
cp = Math.round(cp);
|
||||||
|
sp = intValue % 100;
|
||||||
|
intValue -= sp;
|
||||||
|
sp = Math.round(sp / 10)
|
||||||
|
gp = Math.floor(value);
|
||||||
|
|
||||||
var resultArray = [];
|
var resultArray = [];
|
||||||
//sp
|
|
||||||
var gp = Math.floor(value);
|
|
||||||
if (gp > 0) {
|
if (gp > 0) {
|
||||||
resultArray.push(gp + "gp");
|
resultArray.push(gp + "gp");
|
||||||
}
|
}
|
||||||
//sp
|
|
||||||
var sp = Math.floor(10 * (value % 1));
|
|
||||||
if (sp > 0) {
|
if (sp > 0) {
|
||||||
resultArray.push(sp + "sp");
|
resultArray.push(sp + "sp");
|
||||||
}
|
}
|
||||||
//cp
|
|
||||||
var cp = 10 * ((value * 10) % 1);
|
|
||||||
cp = Math.round(cp * 1000) / 1000;
|
|
||||||
if (cp > 0) {
|
if (cp > 0) {
|
||||||
resultArray.push(cp + "cp");
|
resultArray.push(cp + "cp");
|
||||||
}
|
}
|
||||||
|
|
||||||
//build string with correct spacing
|
//build string with correct spacing
|
||||||
var result = "";
|
var result = "";
|
||||||
for (var i = 0; i < resultArray.length; i++) {
|
for (var i = 0, l = resultArray.length; i < l; i++) {
|
||||||
//add a space between values
|
//add a space between values
|
||||||
if (i !== 0) {
|
if (i !== 0) {
|
||||||
result += " ";
|
result += " ";
|
||||||
|
|||||||
@@ -91,6 +91,6 @@ $thinColumnWidth: 240px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* undo pointer cursor on detail box heading */
|
/* undo pointer cursor on detail box heading */
|
||||||
#globalDetail .card .top {
|
#globalDetail.card .top {
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@
|
|||||||
background-color: #9E9E9E;
|
background-color: #9E9E9E;
|
||||||
}
|
}
|
||||||
|
|
||||||
.blue-grey {
|
.app-grey {
|
||||||
background-color: #607D8B;
|
background-color: #424242;
|
||||||
}
|
}
|
||||||
|
|
||||||
.white {
|
.white {
|
||||||
|
|||||||
@@ -19,6 +19,21 @@ body {
|
|||||||
background-color: #E0E0E0;
|
background-color: #E0E0E0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//fix tabs and core-toolbar having box shadow
|
||||||
|
core-toolbar {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
//give drawer panel a shadow always
|
||||||
|
core-header-panel[drawer] {
|
||||||
|
box-shadow: 2px 0px 5px 0px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Paragraphs
|
||||||
|
p {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
//Horizontal rule
|
//Horizontal rule
|
||||||
hr {
|
hr {
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
@@ -27,7 +42,7 @@ hr {
|
|||||||
color: #444;
|
color: #444;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
margin: 16px -16px;
|
margin: 16px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,4 +15,10 @@ td {
|
|||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.summaryTable {
|
||||||
|
&:nth-child(3){
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,26 +3,26 @@
|
|||||||
<div layout vertical flex>
|
<div layout vertical flex>
|
||||||
<div layout horizontal>
|
<div layout horizontal>
|
||||||
<!--attackBonus-->
|
<!--attackBonus-->
|
||||||
<paper-input id="attackBonusInput"
|
<paper-input class="attackBonusInput"
|
||||||
label="Attack Bonus"
|
label="Attack Bonus"
|
||||||
floatinglabel
|
floatinglabel
|
||||||
value={{attackBonus}}
|
value={{attackBonus}}
|
||||||
flex></paper-input>
|
flex></paper-input>
|
||||||
<!--details-->
|
<!--details-->
|
||||||
<paper-input id="detailInput"
|
<paper-input class="detailInput"
|
||||||
label="Details"
|
label="Details"
|
||||||
floatinglabel
|
floatinglabel
|
||||||
value={{details}}></paper-input>
|
value={{details}}></paper-input>
|
||||||
</div>
|
</div>
|
||||||
<div layout horizontal>
|
<div layout horizontal>
|
||||||
<!--damageBonus-->
|
<!--damageBonus-->
|
||||||
<paper-input id="damageInput"
|
<paper-input class="damageInput"
|
||||||
label="Damage"
|
label="Damage"
|
||||||
floatinglabel
|
floatinglabel
|
||||||
value={{damage}}
|
value={{damage}}
|
||||||
flex></paper-input>
|
flex></paper-input>
|
||||||
<!--DamageType-->
|
<!--DamageType-->
|
||||||
<paper-dropdown-menu id="damageTypeDropdown" label="Damage Type">
|
<paper-dropdown-menu class="damageTypeDropdown" label="Damage Type">
|
||||||
<paper-dropdown layered class="dropdown">
|
<paper-dropdown layered class="dropdown">
|
||||||
<core-menu class="menu" selected={{damageType}}>
|
<core-menu class="menu" selected={{damageType}}>
|
||||||
{{#each damageTypes}}
|
{{#each damageTypes}}
|
||||||
@@ -34,6 +34,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--Delete Button-->
|
<!--Delete Button-->
|
||||||
<paper-icon-button id="deleteAttack" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
<paper-icon-button class="deleteAttack" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -15,23 +15,23 @@ var damageTypes = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
Template.attackEdit.events({
|
Template.attackEdit.events({
|
||||||
"tap #deleteAttack": function(event, instance) {
|
"tap .deleteAttack": function(event, instance) {
|
||||||
Attacks.softRemoveNode(this._id);
|
Attacks.softRemoveNode(this._id);
|
||||||
GlobalUI.deletedToast(this._id, "Attacks", "Attack");
|
GlobalUI.deletedToast(this._id, "Attacks", "Attack");
|
||||||
},
|
},
|
||||||
"change #attackBonusInput": function(event) {
|
"change .attackBonusInput": function(event) {
|
||||||
var value = event.currentTarget.value;
|
var value = event.currentTarget.value;
|
||||||
Attacks.update(this._id, {$set: {attackBonus: value}});
|
Attacks.update(this._id, {$set: {attackBonus: value}});
|
||||||
},
|
},
|
||||||
"change #damageInput": function(event) {
|
"change .damageInput": function(event) {
|
||||||
var value = event.currentTarget.value;
|
var value = event.currentTarget.value;
|
||||||
Attacks.update(this._id, {$set: {damage: value}});
|
Attacks.update(this._id, {$set: {damage: value}});
|
||||||
},
|
},
|
||||||
"change #detailInput": function(event) {
|
"change .detailInput": function(event) {
|
||||||
var value = event.currentTarget.value;
|
var value = event.currentTarget.value;
|
||||||
Attacks.update(this._id, {$set: {details: value}});
|
Attacks.update(this._id, {$set: {details: value}});
|
||||||
},
|
},
|
||||||
"core-select #damageTypeDropdown": function(event) {
|
"core-select .damageTypeDropdown": function(event) {
|
||||||
var detail = event.originalEvent.detail;
|
var detail = event.originalEvent.detail;
|
||||||
if (!detail.isSelected) return;
|
if (!detail.isSelected) return;
|
||||||
var value = detail.item.getAttribute("name");
|
var value = detail.item.getAttribute("name");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template name="characterSettings">
|
<template name="characterSettings">
|
||||||
{{#with character}}
|
{{#with character}}
|
||||||
<div>
|
<div style="height: 100px;">
|
||||||
<table>
|
<table style="width: 100%;">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Hide Spells tab</td>
|
<td>Hide Spells tab</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -23,4 +23,5 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
|
<paper-button id="doneButton" affirmative> Done </paper-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
<template name="shareDialog">
|
<template name="shareDialog">
|
||||||
<div style="width: 360px;">
|
<div style="width: 360px;">
|
||||||
|
<div layout horizontal center>
|
||||||
|
<div>Who can view this character: </div>
|
||||||
|
<paper-dropdown-menu class="visibilityDropdown"
|
||||||
|
label="Visibility">
|
||||||
|
<paper-dropdown layered class="dropdown">
|
||||||
|
<core-menu class="menu visibilityMenu" selected={{viewPermission}}>
|
||||||
|
<paper-item name="whitelist">Only people I share with</paper-item>
|
||||||
|
<paper-item name="public">Anyone with link</paper-item>
|
||||||
|
</core-menu>
|
||||||
|
</paper-dropdown>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{#if readers.count}}
|
{{#if readers.count}}
|
||||||
<div style="font-weight: 500;">
|
<div style="font-weight: 500;">
|
||||||
@@ -7,7 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{#each readers}}
|
{{#each readers}}
|
||||||
<div layout horizontal center>
|
<div layout horizontal center>
|
||||||
<div flex>{{username}}</div>
|
<div flex>{{getUserName}}</div>
|
||||||
<paper-icon-button class="deleteShare" icon="delete"></paper-icon-button>
|
<paper-icon-button class="deleteShare" icon="delete"></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ Template.shareDialog.onCreated(function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
Template.shareDialog.helpers({
|
Template.shareDialog.helpers({
|
||||||
|
viewPermission: function() {
|
||||||
|
var char = Characters.findOne(this._id, {fields: {settings: 1}});
|
||||||
|
return char.settings.viewPermission || "whitelist";
|
||||||
|
},
|
||||||
readers: function(){
|
readers: function(){
|
||||||
var char = Characters.findOne(this._id, {fields: {readers: 1}});
|
var char = Characters.findOne(this._id, {fields: {readers: 1}});
|
||||||
return Meteor.users.find({_id: {$in: char.readers}});
|
return Meteor.users.find({_id: {$in: char.readers}});
|
||||||
@@ -19,9 +23,20 @@ Template.shareDialog.helpers({
|
|||||||
return "User not found";
|
return "User not found";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getUserName: function() {
|
||||||
|
return this.username || "user: " + this._id;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.shareDialog.events({
|
Template.shareDialog.events({
|
||||||
|
"core-select .visibilityDropdown": function(event){
|
||||||
|
var detail = event.originalEvent.detail;
|
||||||
|
if (!detail.isSelected) return;
|
||||||
|
var value = detail.item.getAttribute("name");
|
||||||
|
var char = Characters.findOne(this._id, {fields: {settings: 1}});
|
||||||
|
if (value == char.settings.viewPermission) return;
|
||||||
|
Characters.update(this._id, {$set: {"settings.viewPermission": value}});
|
||||||
|
},
|
||||||
"input #userNameOrEmailInput":
|
"input #userNameOrEmailInput":
|
||||||
function(event, instance){
|
function(event, instance){
|
||||||
var userName = instance.find("#userNameOrEmailInput").value;
|
var userName = instance.find("#userNameOrEmailInput").value;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Template.characterSheet.helpers({
|
|||||||
hideSpellcasting: function() {
|
hideSpellcasting: function() {
|
||||||
var char = Characters.findOne(this._id);
|
var char = Characters.findOne(this._id);
|
||||||
return char && char.settings.hideSpellcasting;
|
return char && char.settings.hideSpellcasting;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.characterSheet.events({
|
Template.characterSheet.events({
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if description}}
|
{{#if description}}
|
||||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{> effectsViewList charId=charId parentId=_id}}
|
{{> effectsViewList charId=charId parentId=_id}}
|
||||||
|
|||||||
@@ -95,14 +95,16 @@
|
|||||||
<core-tooltip label="Feature enabled"
|
<core-tooltip label="Feature enabled"
|
||||||
position="left">
|
position="left">
|
||||||
<paper-checkbox class="enabledCheckbox"
|
<paper-checkbox class="enabledCheckbox"
|
||||||
checked={{enabled}}>
|
checked={{enabled}}
|
||||||
|
disabled={{#unless canEditCharacter charId}}true{{/unless}}>
|
||||||
</paper-checkbox>
|
</paper-checkbox>
|
||||||
</core-tooltip>
|
</core-tooltip>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{#if description}}
|
{{#if description}}
|
||||||
<div flex class="bottom text"
|
<div flex class="bottom">
|
||||||
>{{evaluateString charId description}}</div>
|
{{#markdown}}{{evaluateString charId shortDescription}}{{/markdown}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if hasUses}}
|
{{#if hasUses}}
|
||||||
<div layout horizontal center end-justified>
|
<div layout horizontal center end-justified>
|
||||||
@@ -135,7 +137,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="resource">
|
<template name="resource">
|
||||||
{{#if char.attributeBase name}}
|
{{#if characterCalculate "attributeBase" char._id name}}
|
||||||
<paper-shadow class="card"
|
<paper-shadow class="card"
|
||||||
hero-id="main" {{detailHero name char._id}}
|
hero-id="main" {{detailHero name char._id}}
|
||||||
layout horizontal>
|
layout horizontal>
|
||||||
@@ -152,7 +154,7 @@
|
|||||||
disabled={{cantDecrement}}>
|
disabled={{cantDecrement}}>
|
||||||
</paper-icon-button>
|
</paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<div>{{char.attributeValue name}}</div>
|
<div>{{characterCalculate "attributeValue" char._id name}}</div>
|
||||||
<!--<div>/{{char.attributeBase name}}</div>-->
|
<!--<div>/{{char.attributeBase name}}</div>-->
|
||||||
</div>
|
</div>
|
||||||
<div class="right clickable"
|
<div class="right clickable"
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ Template.features.helpers({
|
|||||||
var features = Features.find({charId: this._id}, {sort: {color: 1, name: 1}});
|
var features = Features.find({charId: this._id}, {sort: {color: 1, name: 1}});
|
||||||
return features;
|
return features;
|
||||||
},
|
},
|
||||||
|
shortDescription: function() {
|
||||||
|
if (_.isString(this.description)){
|
||||||
|
return this.description.split(/^( *[-*_]){3,} *(?:\n+|$)/m)[0];
|
||||||
|
}
|
||||||
|
},
|
||||||
hasUses: function(){
|
hasUses: function(){
|
||||||
return this.usesValue() > 0;
|
return this.usesValue() > 0;
|
||||||
},
|
},
|
||||||
noUsesLeft: function(){
|
noUsesLeft: function(){
|
||||||
return this.usesLeft() <= 0;
|
return this.usesLeft() <= 0 || !canEditCharacter(this.charId);
|
||||||
},
|
},
|
||||||
usesFull: function(){
|
usesFull: function(){
|
||||||
return this.usesLeft() >= this.usesValue();
|
return this.usesLeft() >= this.usesValue() || !canEditCharacter(this.charId);
|
||||||
},
|
},
|
||||||
colorClass: function(){
|
colorClass: function(){
|
||||||
return getColorClass(this.color);
|
return getColorClass(this.color);
|
||||||
@@ -96,16 +101,19 @@ Template.features.events({
|
|||||||
|
|
||||||
Template.resource.helpers({
|
Template.resource.helpers({
|
||||||
cantIncrement: function(){
|
cantIncrement: function(){
|
||||||
var baseBigger = this.char.attributeValue(this.name) <
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
this.char.attributeBase(this.name);
|
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||||
return !baseBigger;
|
var baseBigger = value < base;
|
||||||
|
return !baseBigger || !canEditCharacter(this.char._id);
|
||||||
},
|
},
|
||||||
cantDecrement: function(){
|
cantDecrement: function(){
|
||||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
return !valuePositive;
|
var valuePositive = value > 0;
|
||||||
|
return !valuePositive || !canEditCharacter(this.char._id);
|
||||||
},
|
},
|
||||||
getColor: function(){
|
getColor: function(){
|
||||||
if (this.char.attributeValue(this.name) > 0){
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
|
if (value > 0){
|
||||||
return this.color;
|
return this.color;
|
||||||
} else {
|
} else {
|
||||||
return "grey";
|
return "grey";
|
||||||
@@ -115,14 +123,17 @@ Template.resource.helpers({
|
|||||||
|
|
||||||
Template.resource.events({
|
Template.resource.events({
|
||||||
"tap .resourceUp": function(event){
|
"tap .resourceUp": function(event){
|
||||||
if (this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
|
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||||
|
if (value < base){
|
||||||
var modifier = {$inc: {}};
|
var modifier = {$inc: {}};
|
||||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||||
Characters.update(this.char._id, modifier, {validate: false});
|
Characters.update(this.char._id, modifier, {validate: false});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tap .resourceDown": function(event){
|
"tap .resourceDown": function(event){
|
||||||
if (this.char.attributeValue(this.name) > 0){
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
|
if (value > 0){
|
||||||
var modifier = {$inc: {}};
|
var modifier = {$inc: {}};
|
||||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||||
Characters.update(this.char._id, modifier, {validate: false});
|
Characters.update(this.char._id, modifier, {validate: false});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ var getFractionCarried = function(char) {
|
|||||||
weight += item.totalWeight();
|
weight += item.totalWeight();
|
||||||
});
|
});
|
||||||
//get strength
|
//get strength
|
||||||
var strength = char.attributeValue("strength");
|
var strength = Characters.calculate.attributeValue(char._id, "strength");
|
||||||
var capacity = strength * 15;
|
var capacity = strength * 15;
|
||||||
return weight / capacity;
|
return weight / capacity;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,13 +34,13 @@
|
|||||||
<template name="containerView">
|
<template name="containerView">
|
||||||
<div layout horizontal wrap center justified>
|
<div layout horizontal wrap center justified>
|
||||||
<table class="summaryTable fullwidth">
|
<table class="summaryTable fullwidth">
|
||||||
<tr><td>Container</td><td>{{weight}}lbs</td><td>{{longValueString value}}</td></tr>
|
<tr><td>Container</td><td>{{round weight}}lbs</td><td>{{longValueString value}}</td></tr>
|
||||||
<tr><td>Contents</td><td>{{contentsWeight}}lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
<tr><td>Contents</td><td>{{round contentsWeight}}lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
||||||
<tr class="body2"><td>Total</td><td>{{totalWeight}}lbs</td><td>{{longValueString totalValue}}</td></tr>
|
<tr class="body2"><td>Total</td><td>{{round totalWeight}}lbs</td><td>{{longValueString totalValue}}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{{#if description}}
|
{{#if description}}
|
||||||
<hr class="vertMargin">
|
<hr class="vertMargin">
|
||||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -35,8 +35,7 @@
|
|||||||
<div class="item-slot">
|
<div class="item-slot">
|
||||||
<div class="item buff"
|
<div class="item buff"
|
||||||
hero-id="main" {{detailHero}}
|
hero-id="main" {{detailHero}}
|
||||||
layout horizontal center
|
layout horizontal center>
|
||||||
draggable="true">
|
|
||||||
<div flex>
|
<div flex>
|
||||||
<core-icon icon="work"
|
<core-icon icon="work"
|
||||||
style="margin-right: 16px">
|
style="margin-right: 16px">
|
||||||
@@ -114,6 +113,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<core-tooltip label="Container carried" position="left">
|
<core-tooltip label="Container carried" position="left">
|
||||||
<paper-checkbox class="carriedCheckbox"
|
<paper-checkbox class="carriedCheckbox"
|
||||||
|
disabled={{#unless canEditCharacter charId}}true{{/unless}}
|
||||||
checked={{isCarried}}>
|
checked={{isCarried}}>
|
||||||
</paper-checkbox>
|
</paper-checkbox>
|
||||||
</core-tooltip>
|
</core-tooltip>
|
||||||
@@ -152,11 +152,11 @@
|
|||||||
<div class="item {{hidden}} inventoryItem"
|
<div class="item {{hidden}} inventoryItem"
|
||||||
hero-id="main" {{detailHero}}
|
hero-id="main" {{detailHero}}
|
||||||
layout horizontal center
|
layout horizontal center
|
||||||
draggable="true">
|
draggable={{canEditCharacter charId}}>
|
||||||
<div flex class="itemName">
|
<div flex class="itemName">
|
||||||
{{#if ne1 quantity}}{{quantity}} {{/if}}{{pluralName}}
|
{{#if ne1 quantity}}{{quantity}} {{/if}}{{pluralName}}
|
||||||
</div>
|
</div>
|
||||||
{{#if settings.showIncrement}}
|
{{#if settings.showIncrement}}{{#if canEditCharacter charId}}
|
||||||
<div class="incrementButtons">
|
<div class="incrementButtons">
|
||||||
<paper-icon-button class="addItemQuantity"
|
<paper-icon-button class="addItemQuantity"
|
||||||
icon="add"
|
icon="add"
|
||||||
@@ -166,7 +166,7 @@
|
|||||||
icon="remove"
|
icon="remove"
|
||||||
style="margin-right: -8px"></paper-icon-button>
|
style="margin-right: -8px"></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ Template.inventory.helpers({
|
|||||||
).forEach(function(item){
|
).forEach(function(item){
|
||||||
worth += item.totalValue();
|
worth += item.totalValue();
|
||||||
});
|
});
|
||||||
|
Containers.find(
|
||||||
|
{charId: this._id},
|
||||||
|
{fields: {value : 1}}
|
||||||
|
).forEach(function(container) {
|
||||||
|
if (container.value) worth += container.value;
|
||||||
|
});
|
||||||
return worth;
|
return worth;
|
||||||
},
|
},
|
||||||
weightCarried: function(){
|
weightCarried: function(){
|
||||||
@@ -174,6 +180,20 @@ Template.inventory.events({
|
|||||||
heroId: itemId,
|
heroId: itemId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
"hold .inventoryItem": function(event, instance) {
|
||||||
|
var itemId = this._id;
|
||||||
|
var charId = Template.parentData()._id;
|
||||||
|
var containerId = this.parent.id;
|
||||||
|
GlobalUI.showDialog({
|
||||||
|
template: "moveItemDialog",
|
||||||
|
data: {
|
||||||
|
charId: charId,
|
||||||
|
itemId: itemId,
|
||||||
|
containerId: containerId,
|
||||||
|
},
|
||||||
|
heading: "Move " + this.pluralName(),
|
||||||
|
});
|
||||||
|
},
|
||||||
"tap .incrementButtons": function(event) {
|
"tap .incrementButtons": function(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
{{#if requiresAttunement}}<div class="vertMargin">Requires Attunement</div>{{/if}}
|
{{#if requiresAttunement}}<div class="vertMargin">Requires Attunement</div>{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{#if description}}
|
{{#if description}}
|
||||||
<hr class="vertMargin">
|
<hr style="margin: 16px 0 16px 0;">
|
||||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{> effectsViewList charId=charId parentId=_id}}
|
{{> effectsViewList charId=charId parentId=_id}}
|
||||||
{{> attacksViewList charId=charId parentId=_id}}
|
{{> attacksViewList charId=charId parentId=_id}}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
html /deep/ .moveItemDialog paper-tabs::shadow #selectionBar {
|
||||||
|
background-color: #D50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
html /deep/ .moveItemDialog paper-tab::shadow #ink {
|
||||||
|
color: #D50000;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<template name="moveItemDialog">
|
||||||
|
<div class="moveItemDialog">
|
||||||
|
<paper-tabs selected="{{selectedTab}}">
|
||||||
|
<paper-tab name="containers"
|
||||||
|
class="clickable">
|
||||||
|
Containers
|
||||||
|
</paper-tab>
|
||||||
|
<paper-tab name="characters"
|
||||||
|
class="clickable">
|
||||||
|
Characters
|
||||||
|
</paper-tab>
|
||||||
|
</paper-tabs>
|
||||||
|
<core-animated-pages selected="{{selectedTab}}"
|
||||||
|
transitions="slide-from-right"
|
||||||
|
style="width: 250px;
|
||||||
|
height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;">
|
||||||
|
<section name="containers">
|
||||||
|
<core-menu id="containerMenu" style="margin: 0;">
|
||||||
|
{{#each containers}}
|
||||||
|
<paper-item name={{_id}}
|
||||||
|
layout horizontal center>
|
||||||
|
<core-icon icon="image:brightness-1"
|
||||||
|
style="color: {{hexColor color}};
|
||||||
|
margin-right: 16px;">
|
||||||
|
</core-icon>
|
||||||
|
<div>{{name}}</div>
|
||||||
|
</paper-item>
|
||||||
|
{{/each}}
|
||||||
|
</core-menu>
|
||||||
|
</section>
|
||||||
|
<section name="characters">
|
||||||
|
<core-menu id="characterMenu" style="margin: 0;">
|
||||||
|
{{#each characters}}
|
||||||
|
<paper-item name={{_id}}
|
||||||
|
layout horizontal center>
|
||||||
|
<div class="item small">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
</paper-item>
|
||||||
|
{{/each}}
|
||||||
|
</core-menu>
|
||||||
|
</section>
|
||||||
|
</core-animated-pages>
|
||||||
|
</div>
|
||||||
|
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
|
||||||
|
<paper-button id="moveButton" affirmative> Move </paper-button>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
Template.moveItemDialog.onCreated(function() {
|
||||||
|
Session.setDefault("moveItemDialogTab", "containers");
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.moveItemDialog.helpers({
|
||||||
|
selectedTab: function() {
|
||||||
|
return Session.get("moveItemDialogTab");
|
||||||
|
},
|
||||||
|
characters: function() {
|
||||||
|
var userId = Meteor.userId();
|
||||||
|
return Characters.find(
|
||||||
|
{
|
||||||
|
$or: [
|
||||||
|
{readers: userId},
|
||||||
|
{writers: userId},
|
||||||
|
{owner: userId},
|
||||||
|
],
|
||||||
|
_id: {$ne: this.charId},
|
||||||
|
},
|
||||||
|
{fields: {name: 1}}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
containers: function(){
|
||||||
|
return Containers.find(
|
||||||
|
{
|
||||||
|
charId: this.charId,
|
||||||
|
_id: {$ne: this.containerId},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fields: {color: 1, name: 1},
|
||||||
|
sort: {color: 1, name: 1},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.moveItemDialog.events({
|
||||||
|
"tap paper-tab": function(event) {
|
||||||
|
Session.set("moveItemDialogTab", event.currentTarget.getAttribute("name"));
|
||||||
|
},
|
||||||
|
"tap #moveButton": function(event, instance) {
|
||||||
|
var tab = Session.get("moveItemDialogTab");
|
||||||
|
if (tab === "containers"){
|
||||||
|
var containerId = instance.find("#containerMenu").selected;
|
||||||
|
if (!containerId) throw "no menu selection";
|
||||||
|
Meteor.call("moveItemToContainer", this.itemId, containerId);
|
||||||
|
} else if (tab === "characters"){
|
||||||
|
var characterId = instance.find("#characterMenu").selected;
|
||||||
|
if (!characterId) throw "no menu selection";
|
||||||
|
Meteor.call("moveItemToCharacter", this.itemId, characterId);
|
||||||
|
} else {
|
||||||
|
throw "Move item dialog tab is not set to containers or character," +
|
||||||
|
" it is set to " + tab;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -6,23 +6,27 @@
|
|||||||
</div>
|
</div>
|
||||||
{{#if description}}
|
{{#if description}}
|
||||||
<hr class="vertMargin">
|
<hr class="vertMargin">
|
||||||
<div class="pre-wrap">{{description}}</div>
|
<div>{{#markdown}}{{description}}{{/markdown}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div horizontal layout>
|
{{> experienceEdit}}
|
||||||
<!--Name-->
|
|
||||||
<paper-input id="experienceNameInput" label="Name" floatinglabel value={{name}} flex></paper-input>
|
|
||||||
<!--Value-->
|
|
||||||
<paper-input-decorator label="Value" floatinglabel>
|
|
||||||
<input id="valueInput" type="number" value={{value}}>
|
|
||||||
</paper-input-decorator>
|
|
||||||
</div>
|
|
||||||
<!--Description-->
|
|
||||||
<paper-input-decorator label="Description" floatinglabel layout vertical>
|
|
||||||
<paper-autogrow-textarea>
|
|
||||||
<textarea id="experienceDescriptionInput" placeholder value={{description}}></textarea>
|
|
||||||
</paper-autogrow-textarea>
|
|
||||||
</paper-input-decorator>
|
|
||||||
{{/baseDialog}}
|
{{/baseDialog}}
|
||||||
{{/with}}
|
{{/with}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="experienceEdit">
|
||||||
|
<div horizontal layout>
|
||||||
|
<!--Name-->
|
||||||
|
<paper-input id="experienceNameInput" label="Name" floatinglabel value={{name}} flex></paper-input>
|
||||||
|
<!--Value-->
|
||||||
|
<paper-input-decorator label="Value" floatinglabel>
|
||||||
|
<input id="valueInput" type="number" value={{value}}>
|
||||||
|
</paper-input-decorator>
|
||||||
|
</div>
|
||||||
|
<!--Description-->
|
||||||
|
<paper-input-decorator label="Description" floatinglabel layout vertical>
|
||||||
|
<paper-autogrow-textarea>
|
||||||
|
<textarea id="experienceDescriptionInput" placeholder value={{description}}></textarea>
|
||||||
|
</paper-autogrow-textarea>
|
||||||
|
</paper-input-decorator>
|
||||||
|
</template>
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
Template.experienceEdit.onRendered(function(){
|
||||||
|
updatePolymerInputs(this);
|
||||||
|
});
|
||||||
|
|
||||||
Template.experienceDialog.helpers({
|
Template.experienceDialog.helpers({
|
||||||
experience: function(){
|
experience: function(){
|
||||||
Experiences.findOne(this.experienceId);
|
Experiences.findOne(this.experienceId);
|
||||||
@@ -18,8 +22,10 @@ Template.experienceDialog.events({
|
|||||||
);
|
);
|
||||||
GlobalUI.closeDetail();
|
GlobalUI.closeDetail();
|
||||||
},
|
},
|
||||||
//TODO validate input (integer, non-negative, etc) for these inputs and give validation errors
|
});
|
||||||
"change #experienceNameInput, input #experienceNameInput": function(event){
|
|
||||||
|
Template.experienceEdit.events({
|
||||||
|
"change #experienceNameInput": function(event){
|
||||||
var value = event.currentTarget.value;
|
var value = event.currentTarget.value;
|
||||||
Experiences.update(this._id, {$set: {name: value}});
|
Experiences.update(this._id, {$set: {name: value}});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,8 +9,9 @@
|
|||||||
hero-id="toolbar" {{detailHero}}
|
hero-id="toolbar" {{detailHero}}
|
||||||
layout horizontal center>
|
layout horizontal center>
|
||||||
<div flex>Experience</div>
|
<div flex>Experience</div>
|
||||||
<div >{{experience}} XP</div>
|
<div >{{characterCalculate "experience" _id}} XP</div>
|
||||||
<paper-icon-button class="black54" id="addXP" icon="add"></paper-icon-button>
|
<paper-icon-button class="black54" id="addXP" icon="add"
|
||||||
|
disabled={{#unless canEditCharacter _id}}true{{/unless}}></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom list">
|
<div class="bottom list">
|
||||||
{{#each experiences}}
|
{{#each experiences}}
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
layout horizontal center>
|
layout horizontal center>
|
||||||
<div flex>
|
<div flex>
|
||||||
<div class="containerName subhead">
|
<div class="containerName subhead">
|
||||||
Level {{level}}
|
Level {{characterCalculate "level" _id}}
|
||||||
</div>
|
</div>
|
||||||
{{#if nextLevelXP}}
|
{{#if nextLevelXP}}
|
||||||
<div class="caption">
|
<div class="caption">
|
||||||
@@ -55,7 +56,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<paper-icon-button class="black54"
|
<paper-icon-button class="black54"
|
||||||
id="addClassButton"
|
id="addClassButton"
|
||||||
icon="add">
|
icon="add"
|
||||||
|
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
|
||||||
</paper-icon-button>
|
</paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom list">
|
<div class="bottom list">
|
||||||
@@ -85,7 +87,7 @@
|
|||||||
layout horizontal center>
|
layout horizontal center>
|
||||||
{{name}}
|
{{name}}
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom text">{{description}}</div>
|
<div class="bottom">{{#markdown}}{{description}}{{/markdown}}</div>
|
||||||
</paper-shadow>
|
</paper-shadow>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Template.journal.helpers({
|
|||||||
return Levels.find({charId: charId, classId: this._id}, {sort: {value: 1}});
|
return Levels.find({charId: charId, classId: this._id}, {sort: {value: 1}});
|
||||||
},
|
},
|
||||||
nextLevelXP: function(){
|
nextLevelXP: function(){
|
||||||
var currentLevel = this.level();
|
var currentLevel = Characters.calculate.level(this._id);
|
||||||
if (currentLevel < 20){
|
if (currentLevel < 20){
|
||||||
return XP_TABLE[currentLevel];
|
return XP_TABLE[currentLevel];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template name="noteDialog">
|
<template name="noteDialog">
|
||||||
{{#with note}}
|
{{#with note}}
|
||||||
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
|
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
|
||||||
<div class="pre-wrap">{{description}}</div>
|
<div>{{#markdown}}{{description}}{{/markdown}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{> noteDialogEdit}}
|
{{> noteDialogEdit}}
|
||||||
{{/baseDialog}}
|
{{/baseDialog}}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<template name="backgroundDialog">
|
||||||
|
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true"}}
|
||||||
|
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
|
||||||
|
{{> proficiencyViewList charId=charId parentId=charId parentGroup="background"}}
|
||||||
|
{{else}}
|
||||||
|
{{> textDialogEdit}}
|
||||||
|
{{> proficiencyEditList parentId=charId parentCollection="Characters" charId=charId parentGroup="background"}}
|
||||||
|
{{/baseDialog}}
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Template.backgroundDialog.helpers({
|
||||||
|
value: function(){
|
||||||
|
var fieldSelector = {fields: {}};
|
||||||
|
fieldSelector.fields[this.field] = 1;
|
||||||
|
var char = Characters.findOne(this.charId, fieldSelector);
|
||||||
|
return char[this.field];
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,18 +1,36 @@
|
|||||||
<template name="personaDetailsDialog">
|
<template name="personaDetailsDialog">
|
||||||
{{#baseDialog title=name class="deep-purple white-text" hideColor="true" hideDelete="true" startEditing=startEditing}}
|
{{#baseDialog title=name class="deep-purple white-text" hideColor="true" hideDelete="true" startEditing=startEditing}}
|
||||||
{{alignment}} {{gender}} {{race}}
|
{{#with char}}
|
||||||
|
<div>{{alignment}} {{gender}} {{race}}</div>
|
||||||
|
<core-image style="width: 350px; height: 350px; margin-top: 8px;"
|
||||||
|
sizing="cover"
|
||||||
|
hero-id="image" hero
|
||||||
|
src={{picture}}></core-image>
|
||||||
|
{{/with}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{> personaDetailsEdit}}
|
{{#with char}}
|
||||||
|
{{> personaDetailsEdit}}
|
||||||
|
{{/with}}
|
||||||
{{/baseDialog}}
|
{{/baseDialog}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="personaDetailsEdit">
|
<template name="personaDetailsEdit">
|
||||||
<!--Name-->
|
<div layout horizontal center-justified>
|
||||||
<paper-input id="nameInput" label="Name" floatinglabel value={{name}}></paper-input><br>
|
<div flex style="max-width: 350px;" layout vertical>
|
||||||
<!--Alignment-->
|
<!--Name-->
|
||||||
<paper-input id="alignmentInput" label="Alignment" floatinglabel value={{alignment}}></paper-input><br>
|
<paper-input id="nameInput" label="Name" floatinglabel value={{name}}></paper-input>
|
||||||
<!--Gender-->
|
<!--Alignment-->
|
||||||
<paper-input id="genderInput" label="Gender" floatinglabel value={{gender}}></paper-input><br>
|
<paper-input id="alignmentInput" label="Alignment" floatinglabel value={{alignment}}></paper-input>
|
||||||
<!--Race-->
|
<!--Gender-->
|
||||||
<paper-input id="raceInput" label="Race" floatinglabel value={{race}}></paper-input><br>
|
<paper-input id="genderInput" label="Gender" floatinglabel value={{gender}}></paper-input>
|
||||||
|
<!--Race-->
|
||||||
|
<paper-input id="raceInput" label="Race" floatinglabel value={{race}}></paper-input>
|
||||||
|
<!--Picture-->
|
||||||
|
<paper-input id="pictureInput" label="Picture URL" floatinglabel value={{picture}}></paper-input>
|
||||||
|
<core-image style="height:350px; width: 100%; margin-top: 8px;"
|
||||||
|
sizing="cover"
|
||||||
|
hero-id="image" hero
|
||||||
|
src={{picture}}></core-image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -2,21 +2,34 @@ Template.personaDetailsEdit.onRendered(function(){
|
|||||||
updatePolymerInputs(this);
|
updatePolymerInputs(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Template.personaDetailsDialog.helpers({
|
||||||
|
char: function() {
|
||||||
|
return Characters.findOne(
|
||||||
|
this._id,
|
||||||
|
{fields: {name: 1, alignment: 1, gender: 1, race: 1, picture: 1}}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Template.personaDetailsEdit.events({
|
Template.personaDetailsEdit.events({
|
||||||
"change #nameInput": function(event){
|
"change #nameInput": function(event){
|
||||||
var input = event.currentTarget.value;
|
var input = event.currentTarget.value;
|
||||||
Characters.update(this.charId, {$set: {name: input}});
|
Characters.update(this._id, {$set: {name: input}});
|
||||||
},
|
},
|
||||||
"change #alignmentInput": function(event){
|
"change #alignmentInput": function(event){
|
||||||
var input = event.currentTarget.value;
|
var input = event.currentTarget.value;
|
||||||
Characters.update(this.charId, {$set: {alignment: input}});
|
Characters.update(this._id, {$set: {alignment: input}});
|
||||||
},
|
},
|
||||||
"change #genderInput": function(event){
|
"change #genderInput": function(event){
|
||||||
var input = event.currentTarget.value;
|
var input = event.currentTarget.value;
|
||||||
Characters.update(this.charId, {$set: {gender: input}});
|
Characters.update(this._id, {$set: {gender: input}});
|
||||||
},
|
},
|
||||||
"change #raceInput": function(event){
|
"change #raceInput": function(event){
|
||||||
var input = event.currentTarget.value;
|
var input = event.currentTarget.value;
|
||||||
Characters.update(this.charId, {$set: {race: input}});
|
Characters.update(this._id, {$set: {race: input}});
|
||||||
|
},
|
||||||
|
"change #pictureInput": function(event){
|
||||||
|
var input = event.currentTarget.value;
|
||||||
|
Characters.update(this._id, {$set: {picture: input}});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,35 @@
|
|||||||
<div id="persona" class="scroll-y" fit>
|
<div id="persona" class="scroll-y" fit>
|
||||||
<div class="column-container">
|
<div class="column-container">
|
||||||
{{#with characterDetails}}
|
{{#with characterDetails}}
|
||||||
{{#containerCardHelper this}}{{alignment}} {{gender}} {{race}}{{/containerCardHelper}}
|
<paper-shadow class="card"
|
||||||
|
hero-id="main" {{detailHero "details" _id}}>
|
||||||
|
{{#unless picture}}
|
||||||
|
<div class="top subhead characterField {{colorClass}}"
|
||||||
|
hero-id="toolbar" {{detailHero "details" _id}}>
|
||||||
|
<div class="subhead" flex
|
||||||
|
hero-id="title" {{detailHero "details" _id}}>
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<core-image class="characterField clickable"
|
||||||
|
style="height:350px; width: 100%;
|
||||||
|
background-color: #e8e8e8;"
|
||||||
|
sizing="cover"
|
||||||
|
hero-id="image" {{detailHero "details" _id}}
|
||||||
|
src={{picture}}></core-image>
|
||||||
|
{{/unless}}
|
||||||
|
<div class="bottom">
|
||||||
|
{{#if picture}}
|
||||||
|
<div class="title" hero-id="title" {{detailHero "details" _id}}>
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<div class="subhead">
|
||||||
|
{{alignment}} {{gender}} {{race}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</paper-shadow>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
{{> containerCard characterField "description" "Description"}}
|
{{> containerCard characterField "description" "Description"}}
|
||||||
{{> containerCard characterField "personality" "Personality Traits"}}
|
{{> containerCard characterField "personality" "Personality Traits"}}
|
||||||
@@ -40,6 +68,6 @@
|
|||||||
{{title}}
|
{{title}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom text">{{> UI.contentBlock}}</div>
|
<div class="bottom">{{#markdown}}{{> UI.contentBlock}}{{/markdown}}</div>
|
||||||
</paper-shadow>
|
</paper-shadow>
|
||||||
</template>
|
</template>
|
||||||
@@ -11,12 +11,12 @@ Template.persona.helpers({
|
|||||||
characterDetails: function(){
|
characterDetails: function(){
|
||||||
var char = Characters.findOne(
|
var char = Characters.findOne(
|
||||||
this._id,
|
this._id,
|
||||||
{fields: {name: 1, gender: 1, alignment: 1, race:1}}
|
{fields: {name: 1, gender: 1, alignment: 1, race:1, picture: 1}}
|
||||||
);
|
);
|
||||||
char.field = "details";
|
char.field = "details";
|
||||||
char.title = char.name;
|
char.title = char.name;
|
||||||
char.color = "d";
|
char.color = "d";
|
||||||
char.topClass = "characterField";
|
char.startEditing = true;
|
||||||
return char;
|
return char;
|
||||||
},
|
},
|
||||||
characterField: function(field, title){
|
characterField: function(field, title){
|
||||||
@@ -40,25 +40,28 @@ Template.persona.helpers({
|
|||||||
|
|
||||||
Template.persona.events({
|
Template.persona.events({
|
||||||
"tap .characterField": function(event){
|
"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,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.charId = Template.parentData()._id;
|
this.charId = Template.parentData()._id;
|
||||||
GlobalUI.setDetail({
|
GlobalUI.setDetail({
|
||||||
template: "personaDetailsDialog",
|
template: "personaDetailsDialog",
|
||||||
data: this,
|
data: this,
|
||||||
heroId: this._id + this.field,
|
heroId: this._id + this.field,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
var template = "textDialog";
|
||||||
|
if (this.field === "backstory") template = "backgroundDialog";
|
||||||
|
var charId = Template.parentData()._id;
|
||||||
|
GlobalUI.setDetail({
|
||||||
|
template: template,
|
||||||
|
data: {
|
||||||
|
charId: charId,
|
||||||
|
field: this.field,
|
||||||
|
title: this.title,
|
||||||
|
color: this.color,
|
||||||
|
startEditing: true,
|
||||||
|
},
|
||||||
|
heroId: this._id + this.field,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template name="textDialog">
|
<template name="textDialog">
|
||||||
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
|
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
|
||||||
<div class="pre-wrap">{{evaluateString charId value}}</div>
|
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{> textDialogEdit}}
|
{{> textDialogEdit}}
|
||||||
{{/baseDialog}}
|
{{/baseDialog}}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
<template name="proficiencyView">
|
<template name="proficiencyView">
|
||||||
<div class="proficiencyView" layout horizontal center>
|
<div class="proficiencyView item small"
|
||||||
<core-icon icon="{{profIcon}}"></core-icon>
|
style="padding: 0;"
|
||||||
<div class="sideMargin">{{getName}}</div>
|
layout horizontal center>
|
||||||
|
<core-icon icon="{{profIcon}}" style="margin-right: 16px;"></core-icon>
|
||||||
|
<div>{{getName}}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{{#if proficiencies.count}}
|
{{#if proficiencies.count}}
|
||||||
<hr class="vertMargin">
|
<hr class="vertMargin">
|
||||||
<div class="proficiencies">
|
<div class="proficiencies">
|
||||||
<h2 class="spaceAfter">Proficiencies</h2>
|
<h2 style="margin-bottom: 8px;">Proficiencies</h2>
|
||||||
{{#each proficiencies}}
|
{{#each proficiencies}}
|
||||||
{{> proficiencyView}}
|
{{> proficiencyView}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|||||||
@@ -9,24 +9,33 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="spellDetails">
|
<template name="spellDetails">
|
||||||
<div class="caption">
|
<div class="body2">
|
||||||
Level {{level}} {{school}}, {{preparedString}}
|
Level {{level}} {{school}}, {{preparedString}}
|
||||||
</div>
|
</div>
|
||||||
<div class="vertMargin">
|
<div style="margin: 16px 0 16px 0;">
|
||||||
|
{{#if castingTime}}
|
||||||
<div>
|
<div>
|
||||||
<span class="body2">Casting Time: </span><span>{{castingTime}}</span>
|
<span class="body2">Casting Time: </span><span>{{castingTime}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if range}}
|
||||||
<div>
|
<div>
|
||||||
<span class="body2">Range: </span><span>{{range}}</span>
|
<span class="body2">Range: </span><span>{{range}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if getComponents}}
|
||||||
<div>
|
<div>
|
||||||
<span class="body2">Components: </span><span>{{getComponents}}</span>
|
<span class="body2">Components: </span><span>{{getComponents}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if duration}}
|
||||||
<div>
|
<div>
|
||||||
<span class="body2">Duration: </span><span>{{duration}}</span>
|
<span class="body2">Duration: </span><span>{{duration}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||||
|
{{> attacksViewList charId=charId parentId=_id}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="spellEdit">
|
<template name="spellEdit">
|
||||||
@@ -126,4 +135,5 @@
|
|||||||
<textarea id="descriptionInput" placeholder value={{description}}></textarea>
|
<textarea id="descriptionInput" placeholder value={{description}}></textarea>
|
||||||
</paper-autogrow-textarea>
|
</paper-autogrow-textarea>
|
||||||
</paper-input-decorator>
|
</paper-input-decorator>
|
||||||
|
{{> attackEditList parentId=_id parentCollection="Spells" charId=charId enabled=true name=name}}
|
||||||
</template>
|
</template>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<hr class="vertMargin">
|
<hr class="vertMargin">
|
||||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<!--Name-->
|
<!--Name-->
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
<core-tooltip label="Change prepared spells"
|
<core-tooltip label="Change prepared spells"
|
||||||
position="left">
|
position="left">
|
||||||
<paper-icon-button class="prepSpells"
|
<paper-icon-button class="prepSpells"
|
||||||
|
disabled={{#unless canEditCharacter charId}}true{{/unless}}
|
||||||
icon="book">
|
icon="book">
|
||||||
</paper-icon-button>
|
</paper-icon-button>
|
||||||
</core-tooltip>
|
</core-tooltip>
|
||||||
|
|||||||
@@ -84,39 +84,35 @@ Template.spells.helpers({
|
|||||||
},
|
},
|
||||||
cantCast: function(level, char){
|
cantCast: function(level, char){
|
||||||
for (var i = level; i <= 9; i++){
|
for (var i = level; i <= 9; i++){
|
||||||
if (char.attributeValue("level" + i + "SpellSlots") > 0){
|
if (Characters.calculate.attributeValue(char._id, "level" + i + "SpellSlots") > 0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
baseSlots: function(char){
|
|
||||||
return char.attributeBase("level" + this.level + "SpellSlots");
|
|
||||||
},
|
|
||||||
slots: function(char){
|
|
||||||
return char.attributeValue("level" + this.level + "SpellSlots");
|
|
||||||
},
|
|
||||||
showSlots: function(char){
|
showSlots: function(char){
|
||||||
return this.level && char.attributeBase("level" + this.level + "SpellSlots");
|
return this.level && Characters.calculate.attributeBase(
|
||||||
|
char._id, "level" + this.level + "SpellSlots"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
hasSlots: function(){
|
hasSlots: function(){
|
||||||
for (var i = 1; i <= 9; i += 1){
|
for (var i = 1; i <= 9; i += 1){
|
||||||
if (this.attributeBase("level" + i + "SpellSlots")){
|
if (Characters.calculate.attributeBase(this._id, "level" + i + "SpellSlots")){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
slotBubbles: function(char){
|
slotBubbles: function(char){
|
||||||
var baseSlots = char.attributeBase("level" + this.level + "SpellSlots");
|
var baseSlots = Characters.calculate.attributeBase(char._id, "level" + this.level + "SpellSlots");
|
||||||
var currentSlots = char.attributeValue("level" + this.level + "SpellSlots");
|
var currentSlots = Characters.calculate.attributeValue(char._id, "level" + this.level + "SpellSlots");
|
||||||
var slotsUsed = baseSlots - currentSlots;
|
var slotsUsed = baseSlots - currentSlots;
|
||||||
var bubbles = [];
|
var bubbles = [];
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < currentSlots; i++){
|
for (i = 0; i < currentSlots; i++){
|
||||||
bubbles.push({
|
bubbles.push({
|
||||||
icon: "radio-button-on",
|
icon: "radio-button-on",
|
||||||
disabled: i !== currentSlots - 1, //last full slot not disabled
|
disabled: i !== currentSlots - 1 || !canEditCharacter(char._id), //last full slot not disabled
|
||||||
attribute: "level" + this.level + "SpellSlots",
|
attribute: "level" + this.level + "SpellSlots",
|
||||||
charId: char._id,
|
charId: char._id,
|
||||||
});
|
});
|
||||||
@@ -124,7 +120,7 @@ Template.spells.helpers({
|
|||||||
for (i = 0; i < slotsUsed; i++){
|
for (i = 0; i < slotsUsed; i++){
|
||||||
bubbles.push({
|
bubbles.push({
|
||||||
icon: "radio-button-off",
|
icon: "radio-button-off",
|
||||||
disabled: i !== 0, //first empty slot not disabled
|
disabled: i !== 0 || !canEditCharacter(char._id), //first empty slot not disabled
|
||||||
attribute: "level" + this.level + "SpellSlots",
|
attribute: "level" + this.level + "SpellSlots",
|
||||||
charId: char._id,
|
charId: char._id,
|
||||||
});
|
});
|
||||||
@@ -143,15 +139,15 @@ Template.spells.events({
|
|||||||
var char = Characters.findOne(this.charId);
|
var char = Characters.findOne(this.charId);
|
||||||
if (event.currentTarget.icon === "radio-button-off"){
|
if (event.currentTarget.icon === "radio-button-off"){
|
||||||
if (
|
if (
|
||||||
char.attributeValue(this.attribute) <
|
Characters.calculate.attributeValue(char._id, this.attribute) <
|
||||||
char.attributeBase(this.attribute)
|
Characters.calculate.attributeBase(char._id, this.attribute)
|
||||||
){
|
){
|
||||||
modifier = {$inc: {}};
|
modifier = {$inc: {}};
|
||||||
modifier.$inc[this.attribute + ".adjustment"] = 1;
|
modifier.$inc[this.attribute + ".adjustment"] = 1;
|
||||||
Characters.update(this.charId, modifier, {validate: false});
|
Characters.update(this.charId, modifier, {validate: false});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (char.attributeValue(this.attribute) > 0){
|
if (Characters.calculate.attributeValue(char._id, this.attribute) > 0){
|
||||||
modifier = {$inc: {}};
|
modifier = {$inc: {}};
|
||||||
modifier.$inc[this.attribute + ".adjustment"] = -1;
|
modifier.$inc[this.attribute + ".adjustment"] = -1;
|
||||||
Characters.update(this.charId, modifier, {validate: false});
|
Characters.update(this.charId, modifier, {validate: false});
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
layout horizontal>
|
layout horizontal>
|
||||||
<div class="left white-text {{color}}"
|
<div class="left white-text {{color}}"
|
||||||
hero-id="toolbar" {{detailHero ability ../_id}}>
|
hero-id="toolbar" {{detailHero ability ../_id}}>
|
||||||
<div class="display1">{{../attributeValue ability}}</div>
|
<div class="display1">{{characterCalculate "attributeValue" ../_id ability}}</div>
|
||||||
<div class="title">{{../abilityMod ability}}</div>
|
<div class="title">{{abilityMod}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right subhead" layout horizontal center>
|
<div class="right subhead" layout horizontal center>
|
||||||
{{title}}
|
{{title}}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Template.abilityMiniCard.helpers({
|
||||||
|
abilityMod: function() {
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.abilityMod(
|
||||||
|
Template.parentData()._id, this.ability
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -106,10 +106,8 @@ Template.attributeDialogView.helpers({
|
|||||||
return a || b || c;
|
return a || b || c;
|
||||||
},
|
},
|
||||||
adjustment: function(){
|
adjustment: function(){
|
||||||
var char = Characters.findOne(this.charId);
|
var value = Characters.calculate.attributeValue(this.charId, this.statName);
|
||||||
if (!char) return;
|
var base = Characters.calculate.attributeBase(this.charId, this.statName);
|
||||||
var value = char.attributeValue(this.statName);
|
|
||||||
var base = char.attributeBase(this.statName);
|
|
||||||
return value - base;
|
return value - base;
|
||||||
},
|
},
|
||||||
baseEffects: function(){
|
baseEffects: function(){
|
||||||
@@ -138,14 +136,10 @@ Template.attributeDialogView.helpers({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
attributeBase: function(){
|
attributeBase: function(){
|
||||||
var char = Characters.findOne(this.charId);
|
return Characters.calculate.attributeBase(this.charId, this.statName);
|
||||||
if (!char) throw "character is " + char;
|
|
||||||
return char.attributeBase(this.statName);
|
|
||||||
},
|
},
|
||||||
attributeValue: function() {
|
attributeValue: function() {
|
||||||
var char = Characters.findOne(this.charId);
|
return Characters.calculate.attributeValue(this.charId, this.statName);
|
||||||
if (!char) throw "character is " + char;
|
|
||||||
return char.attributeValue(this.statName);
|
|
||||||
},
|
},
|
||||||
sourceName: function(){
|
sourceName: function(){
|
||||||
if (this.parent.group === "racial"){
|
if (this.parent.group === "racial"){
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.healthCard paper-slider{
|
.healthCard paper-diff-slider{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,28 +6,33 @@
|
|||||||
hero-id="toolbar" {{detailHero "hitPoints" _id}}
|
hero-id="toolbar" {{detailHero "hitPoints" _id}}
|
||||||
layout vertical center center-justified>
|
layout vertical center center-justified>
|
||||||
<div class="hitPointTitle clickable">Hit Points</div>
|
<div class="hitPointTitle clickable">Hit Points</div>
|
||||||
<paper-icon-button class="white54" id="addTempHP" icon="add"></paper-icon-button>
|
<paper-icon-button class="white54"
|
||||||
|
id="addTempHP"
|
||||||
|
icon="add"
|
||||||
|
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
|
||||||
|
</paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="right" flex layout vertical center-justified style="min-width: 180px;">
|
<div class="right" flex layout vertical center-justified style="min-width: 180px;">
|
||||||
<div layout horizontal>
|
<div layout horizontal>
|
||||||
<paper-slider id="hitPointSlider"
|
<paper-diff-slider id="hitPointSlider"
|
||||||
value={{attributeValue "hitPoints"}}
|
value={{characterCalculate "attributeValue" _id "hitPoints"}}
|
||||||
max={{attributeBase "hitPoints"}}
|
max={{characterCalculate "attributeBase" _id "hitPoints"}}
|
||||||
editable pin
|
editable pin
|
||||||
role="slider"
|
disabled={{#unless canEditCharacter _id}}true{{/unless}}
|
||||||
></paper-slider>
|
role="slider">
|
||||||
|
</paper-diff-slider>
|
||||||
</div>
|
</div>
|
||||||
{{#each tempHitPoints}}
|
{{#each tempHitPoints}}
|
||||||
<div>
|
<div>
|
||||||
{{name}}
|
{{name}}
|
||||||
<div layout horizontal>
|
<div layout horizontal>
|
||||||
<paper-slider class="tempHitPointSlider"
|
<paper-diff-slider class="tempHitPointSlider"
|
||||||
value={{left}}
|
value={{left}}
|
||||||
max={{maximum}}
|
max={{maximum}}
|
||||||
editable pin
|
editable pin
|
||||||
role="slider"
|
role="slider"
|
||||||
flex
|
flex
|
||||||
></paper-slider>
|
></paper-diff-slider>
|
||||||
{{#unless left}}{{#unless deleteOnZero}}
|
{{#unless left}}{{#unless deleteOnZero}}
|
||||||
<paper-icon-button class="deleteTHP" icon="delete"></paper-icon-button>
|
<paper-icon-button class="deleteTHP" icon="delete"></paper-icon-button>
|
||||||
{{/unless}}{{/unless}}
|
{{/unless}}{{/unless}}
|
||||||
@@ -35,9 +40,21 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
<div class="caption">
|
<div class="caption">
|
||||||
{{#if multipliers.immunities.length}} <div>Immune: {{#each multipliers.immunities}} {{name}} {{/each}}</div>{{/if}}
|
{{#if multipliers.immunities.length}}
|
||||||
{{#if multipliers.resistances.length}}<div>Resistance: {{#each multipliers.resistances}} {{name}} {{/each}}</div>{{/if}}
|
<div>
|
||||||
{{#if multipliers.weaknesses.length}} <div>Weakness: {{#each multipliers.weaknesses}} {{name}} {{/each}}</div>{{/if}}
|
Immune: {{#each multipliers.immunities}} {{name}} {{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if multipliers.resistances.length}}
|
||||||
|
<div>
|
||||||
|
Resistance: {{#each multipliers.resistances}} {{name}} {{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if multipliers.weaknesses.length}}
|
||||||
|
<div>
|
||||||
|
Weakness: {{#each multipliers.weaknesses}} {{name}} {{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{#if showDeathSave}}
|
{{#if showDeathSave}}
|
||||||
{{#with deathSaveObject}}
|
{{#with deathSaveObject}}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Template.healthCard.helpers({
|
|||||||
return TemporaryHitPoints.find({charId: this._id});
|
return TemporaryHitPoints.find({charId: this._id});
|
||||||
},
|
},
|
||||||
showDeathSave: function(){
|
showDeathSave: function(){
|
||||||
return this.attributeValue("hitPoints") <= 0;
|
return Characters.calculate.attributeValue(this._id, "hitPoints") <= 0;
|
||||||
},
|
},
|
||||||
deathSaveObject: function(){
|
deathSaveObject: function(){
|
||||||
var char = Characters.findOne(this._id, {fields: {deathSave: 1}});
|
var char = Characters.findOne(this._id, {fields: {deathSave: 1}});
|
||||||
@@ -27,21 +27,20 @@ Template.healthCard.helpers({
|
|||||||
return this.fail >= 3;
|
return this.fail >= 3;
|
||||||
},
|
},
|
||||||
multipliers: function(){
|
multipliers: function(){
|
||||||
var char = Characters.findOne(this._id, {fields: {_id: 1}});
|
|
||||||
var multipliers = [
|
var multipliers = [
|
||||||
{name: "Acid", value: char.attributeValue("acidMultiplier", 1)},
|
{name: "Acid", value: Characters.calculate.attributeValue(this._id, "acidMultiplier")},
|
||||||
{name: "Bludgeoning", value: char.attributeValue("bludgeoningMultiplier", 1)},
|
{name: "Bludgeoning", value: Characters.calculate.attributeValue(this._id, "bludgeoningMultiplier")},
|
||||||
{name: "Cold", value: char.attributeValue("coldMultiplier", 1)},
|
{name: "Cold", value: Characters.calculate.attributeValue(this._id, "coldMultiplier")},
|
||||||
{name: "Fire", value: char.attributeValue("fireMultiplier", 1)},
|
{name: "Fire", value: Characters.calculate.attributeValue(this._id, "fireMultiplier")},
|
||||||
{name: "Force", value: char.attributeValue("forceMultiplier", 1)},
|
{name: "Force", value: Characters.calculate.attributeValue(this._id, "forceMultiplier")},
|
||||||
{name: "Lightning", value: char.attributeValue("lightningMultiplier", 1)},
|
{name: "Lightning", value: Characters.calculate.attributeValue(this._id, "lightningMultiplier")},
|
||||||
{name: "Necrotic", value: char.attributeValue("necroticMultiplier", 1)},
|
{name: "Necrotic", value: Characters.calculate.attributeValue(this._id, "necroticMultiplier")},
|
||||||
{name: "Piercing", value: char.attributeValue("piercingMultiplier", 1)},
|
{name: "Piercing", value: Characters.calculate.attributeValue(this._id, "piercingMultiplier")},
|
||||||
{name: "Poison", value: char.attributeValue("poisonMultiplier", 1)},
|
{name: "Poison", value: Characters.calculate.attributeValue(this._id, "poisonMultiplier")},
|
||||||
{name: "Psychic", value: char.attributeValue("psychicMultiplier", 1)},
|
{name: "Psychic", value: Characters.calculate.attributeValue(this._id, "psychicMultiplier")},
|
||||||
{name: "Radiant", value: char.attributeValue("radiantMultiplier", 1)},
|
{name: "Radiant", value: Characters.calculate.attributeValue(this._id, "radiantMultiplier")},
|
||||||
{name: "Slashing", value: char.attributeValue("slashingMultiplier", 1)},
|
{name: "Slashing", value: Characters.calculate.attributeValue(this._id, "slashingMultiplier")},
|
||||||
{name: "Thunder", value: char.attributeValue("thunderMultiplier", 1)},
|
{name: "Thunder", value: Characters.calculate.attributeValue(this._id, "thunderMultiplier")},
|
||||||
];
|
];
|
||||||
multipliers = _.groupBy(multipliers, "value");
|
multipliers = _.groupBy(multipliers, "value");
|
||||||
return {
|
return {
|
||||||
@@ -55,7 +54,8 @@ Template.healthCard.helpers({
|
|||||||
Template.healthCard.events({
|
Template.healthCard.events({
|
||||||
"change #hitPointSlider": function(event){
|
"change #hitPointSlider": function(event){
|
||||||
var value = event.currentTarget.value;
|
var value = event.currentTarget.value;
|
||||||
var adjustment = value - this.attributeBase("hitPoints");
|
var base = Characters.calculate.attributeBase(this._id, "hitPoints")
|
||||||
|
var adjustment = value - base;
|
||||||
Characters.update(this._id, {$set: {"hitPoints.adjustment": adjustment}});
|
Characters.update(this._id, {$set: {"hitPoints.adjustment": adjustment}});
|
||||||
//reset the death saves if we are gaining HP
|
//reset the death saves if we are gaining HP
|
||||||
if (value > 0)
|
if (value > 0)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template name="hitDice">
|
<template name="hitDice">
|
||||||
{{#if ../attributeBase name}}
|
{{#if characterCalculate "attributeBase" ../_id name}}
|
||||||
<paper-shadow class="card hit-dice" hero-id="main"
|
<paper-shadow class="card hit-dice" hero-id="main"
|
||||||
{{detailHero name ../_id}}
|
{{detailHero name ../_id}}
|
||||||
layout horizontal>
|
layout horizontal>
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="resourceValue" layout vertical center>
|
<div class="resourceValue" layout vertical center>
|
||||||
<div>
|
<div>
|
||||||
{{../attributeValue name}}
|
{{characterCalculate "attributeValue" ../_id name}}
|
||||||
</div>
|
</div>
|
||||||
<div class="title white-text">
|
<div class="title white-text">
|
||||||
d{{diceNum}} {{../abilityMod "constitution"}}
|
d{{diceNum}} {{conMod}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,25 +1,33 @@
|
|||||||
Template.hitDice.helpers({
|
Template.hitDice.helpers({
|
||||||
cantIncrement: function(){
|
cantIncrement: function(){
|
||||||
var valueSmallerThanBase = this.char.attributeValue(this.name) <
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
this.char.attributeBase(this.name);
|
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||||
return !valueSmallerThanBase;
|
return value >= base || !canEditCharacter(this.char._id);
|
||||||
},
|
},
|
||||||
cantDecrement: function(){
|
cantDecrement: function(){
|
||||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
return !valuePositive;
|
return value <= 0 || !canEditCharacter(this.char._id);
|
||||||
|
},
|
||||||
|
conMod: function(){
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.abilityMod(this.char._id, "constitution")
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.hitDice.events({
|
Template.hitDice.events({
|
||||||
"tap .resourceUp": function(event){
|
"tap .resourceUp": function(event){
|
||||||
if (this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
|
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||||
|
if (value < base){
|
||||||
var modifier = {$inc: {}};
|
var modifier = {$inc: {}};
|
||||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||||
Characters.update(this.char._id, modifier, {validate: false});
|
Characters.update(this.char._id, modifier, {validate: false});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tap .resourceDown": function(event){
|
"tap .resourceDown": function(event){
|
||||||
if (this.char.attributeValue(this.name) > 0){
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
|
if (value > 0){
|
||||||
var modifier = {$inc: {}};
|
var modifier = {$inc: {}};
|
||||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||||
Characters.update(this.char._id, modifier, {validate: false});
|
Characters.update(this.char._id, modifier, {validate: false});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- needs name, char, and skillName -->
|
<!-- needs name, charId, and skillName -->
|
||||||
<template name="skillDialog">
|
<template name="skillDialog">
|
||||||
{{#baseDialog title=name class=color hideEdit=true}}
|
{{#baseDialog title=name class=color hideEdit=true}}
|
||||||
{{> skillDialogView}}
|
{{> skillDialogView}}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<template name="skillDialogView">
|
<template name="skillDialogView">
|
||||||
<div layout vertical center>
|
<div layout vertical center>
|
||||||
<div class="display2">
|
<div class="display2">
|
||||||
{{char.skillMod skillName}}
|
{{characterCalculate "skillMod" charId skillName}}
|
||||||
</div>
|
</div>
|
||||||
<div class="subhead">
|
<div class="subhead">
|
||||||
<core-icon icon="{{profIcon}}" class="black54"></core-icon>
|
<core-icon icon="{{profIcon}}" class="black54"></core-icon>
|
||||||
@@ -25,9 +25,9 @@
|
|||||||
<table class="summaryTable">
|
<table class="summaryTable">
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{abilityName}}</td>
|
<td>{{abilityName}}</td>
|
||||||
<td>{{char.abilityMod ability}}</td>
|
<td>{{characterCalculate "abilityMod" charId ability}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{#if char.proficiency skillName}}
|
{{#if characterCalculate "proficiency" charId skillName}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{proficiencyValue}}</td>
|
<td>{{proficiencyValue}}</td>
|
||||||
<td>{{signedString profBonus}}</td>
|
<td>{{signedString profBonus}}</td>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
<tr class="body2">
|
<tr class="body2">
|
||||||
<td>Total</td>
|
<td>Total</td>
|
||||||
<td>{{char.skillMod skillName}}</td>
|
<td>{{characterCalculate "skillMod" charId skillName}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -106,9 +106,7 @@ Template.skillDialogView.helpers({
|
|||||||
return a || b || c;
|
return a || b || c;
|
||||||
},
|
},
|
||||||
profIcon: function(){
|
profIcon: function(){
|
||||||
var char = Characters.findOne(this.charId);
|
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||||
if (!char) return;
|
|
||||||
var prof = char.proficiency(this.skillName);
|
|
||||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||||
if (prof === 1) return "image:brightness-1";
|
if (prof === 1) return "image:brightness-1";
|
||||||
if (prof > 1) return "av:album";
|
if (prof > 1) return "av:album";
|
||||||
@@ -123,13 +121,13 @@ Template.skillDialogView.helpers({
|
|||||||
profBonus: function(){
|
profBonus: function(){
|
||||||
var char = Characters.findOne(this.charId);
|
var char = Characters.findOne(this.charId);
|
||||||
if (!char) return;
|
if (!char) return;
|
||||||
return char.proficiency(this.skillName) *
|
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||||
char.attributeValue("proficiencyBonus");
|
var proficiencyBonus =
|
||||||
|
Characters.calculate.attributeValue(this.charId, "proficiencyBonus");
|
||||||
|
return prof * proficiencyBonus;
|
||||||
},
|
},
|
||||||
proficiencyValue: function(){
|
proficiencyValue: function(){
|
||||||
var char = Characters.findOne(this.charId);
|
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||||
if (!char) return;
|
|
||||||
var prof = char.proficiency(this.skillName);
|
|
||||||
if (prof == 0.5) return "Half Proficiency";
|
if (prof == 0.5) return "Half Proficiency";
|
||||||
if (prof == 1) return "Proficient";
|
if (prof == 1) return "Proficient";
|
||||||
if (prof == 2) return "Double Proficiency";
|
if (prof == 2) return "Double Proficiency";
|
||||||
@@ -199,20 +197,21 @@ Template.skillDialogView.helpers({
|
|||||||
return skill.ability;
|
return skill.ability;
|
||||||
},
|
},
|
||||||
abilityName: function(){
|
abilityName: function(){
|
||||||
var opts = {fields: {}};
|
var skill = Characters.calculate.getField(this.charId, this.skillName);
|
||||||
opts.fields[this.skillName] = 1;
|
|
||||||
var char = Characters.findOne(this.charId, opts);
|
|
||||||
if (!char) return;
|
|
||||||
var skill = char[this.skillName];
|
|
||||||
if (!skill) return;
|
if (!skill) return;
|
||||||
var ability = skill.ability;
|
var ability = skill.ability;
|
||||||
return abilities[ability] && abilities[ability].name;
|
return abilities[ability] && abilities[ability].name;
|
||||||
},
|
},
|
||||||
char: function(){
|
|
||||||
return Characters.findOne(this.charId, {fields:{_id: 1}});
|
|
||||||
},
|
|
||||||
sourceName: function(){
|
sourceName: function(){
|
||||||
if (this.parent.collection === "Characters") return "inate";
|
if (this.parent.collection === "Characters"){
|
||||||
|
if (this.parent.group === "racial"){
|
||||||
|
return Characters.calculate.getField(this.charId, "race") || "Race";
|
||||||
|
}
|
||||||
|
if (this.parent.group === "background"){
|
||||||
|
return "Background";
|
||||||
|
}
|
||||||
|
return "Innate";
|
||||||
|
}
|
||||||
return this.getParent().name;
|
return this.getParent().name;
|
||||||
},
|
},
|
||||||
operationName: function(){
|
operationName: function(){
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
{{#if failSkill}}
|
{{#if failSkill}}
|
||||||
<div class="fail skill-mod">fail</div>
|
<div class="fail skill-mod">fail</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="{{advantage}} skill-mod">{{../skillMod skill}}</div>
|
<div class="{{advantage}} skill-mod">
|
||||||
|
{{skillMod}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div flex>
|
<div flex>
|
||||||
{{name}}
|
{{name}}
|
||||||
@@ -16,7 +18,7 @@
|
|||||||
*
|
*
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if showPassive}}
|
{{#if showPassive}}
|
||||||
({{../passiveSkill skill}})
|
({{characterCalculate "passiveSkill" ../_id skill}})
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
Template.skillRow.helpers({
|
Template.skillRow.helpers({
|
||||||
|
skillMod: function() {
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.skillMod(
|
||||||
|
Template.parentData()._id, this.skill
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
profIcon: function(){
|
profIcon: function(){
|
||||||
var prof = Template.parentData(1).proficiency(this.skill);
|
var charId = Template.parentData()._id;
|
||||||
|
var prof = Characters.calculate.proficiency(charId, this.skill);
|
||||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||||
if (prof === 1) return "image:brightness-1";
|
if (prof === 1) return "image:brightness-1";
|
||||||
if (prof > 1) return "av:album";
|
if (prof > 1) return "av:album";
|
||||||
return "radio-button-off";
|
return "radio-button-off";
|
||||||
},
|
},
|
||||||
failSkill: function(){
|
failSkill: function(){
|
||||||
var charId = Template.parentData(1)._id;
|
var charId = Template.parentData()._id;
|
||||||
return Effects.find({
|
return Effects.find({
|
||||||
charId: charId,
|
charId: charId,
|
||||||
stat: this.skill,
|
stat: this.skill,
|
||||||
@@ -16,12 +24,13 @@ Template.skillRow.helpers({
|
|||||||
}).count();
|
}).count();
|
||||||
},
|
},
|
||||||
advantage: function(){
|
advantage: function(){
|
||||||
var advantage = Template.parentData(1).advantage(this.skill);
|
var charId = Template.parentData()._id;
|
||||||
|
var advantage = Characters.calculate.advantage(charId, this.skill);
|
||||||
if (advantage > 0) return "advantage";
|
if (advantage > 0) return "advantage";
|
||||||
if (advantage < 0) return "disadvantage";
|
if (advantage < 0) return "disadvantage";
|
||||||
},
|
},
|
||||||
conditionalCount: function(){
|
conditionalCount: function(){
|
||||||
var charId = Template.parentData(1)._id;
|
var charId = Template.parentData()._id;
|
||||||
return Effects.find({
|
return Effects.find({
|
||||||
charId: charId,
|
charId: charId,
|
||||||
stat: this.skill,
|
stat: this.skill,
|
||||||
|
|||||||
@@ -75,9 +75,9 @@
|
|||||||
<div class="left display1 white-text {{color}}"
|
<div class="left display1 white-text {{color}}"
|
||||||
hero-id="toolbar" {{detailHero stat ../_id}}>
|
hero-id="toolbar" {{detailHero stat ../_id}}>
|
||||||
{{#if isSkill}}
|
{{#if isSkill}}
|
||||||
{{../skillMod stat}}
|
{{prefix}}{{skillMod}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{prefix}}{{../attributeValue stat}}
|
{{prefix}}{{characterCalculate "attributeValue" ../_id stat}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="right subhead" flex horizontal layout center>
|
<div class="right subhead" flex horizontal layout center>
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ Template.stats.events({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.stats.helpers({
|
Template.statCard.helpers({
|
||||||
|
skillMod: function() {
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.skillMod(
|
||||||
|
Template.parentData()._id, this.stat
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template name="characterList">
|
<template name="characterList">
|
||||||
<core-toolbar class="blue-grey white-text">
|
<core-toolbar class="app-grey white-text">
|
||||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
<div flex>
|
<div flex>
|
||||||
Characters
|
Characters
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ Template.characterSideList.helpers({
|
|||||||
{owner: userId},
|
{owner: userId},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{fields: {name: 1}}
|
{
|
||||||
|
fields: {name: 1},
|
||||||
|
sort: {name: 1},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
<template name="guide">
|
<template name="guide">
|
||||||
|
<core-toolbar class="app-grey white-text">
|
||||||
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
|
<div flex>Guide</div>
|
||||||
|
</core-toolbar>
|
||||||
<div layout vertical center>
|
<div layout vertical center>
|
||||||
<paper-shadow class="wallOfText card" style="padding: 32px; max-width: 800px;">
|
<paper-shadow class="wallOfText card" style="padding: 32px; max-width: 800px;">
|
||||||
<h1>Dicecloud Beta</h1>
|
|
||||||
<p>Welcome to the Dicecloud beta.</p>
|
|
||||||
<p>The beta is going to start with just the character sheet. You can play D&D without minis and maps, without a pre-written adventure, you can play without a lot of things, but the character sheet is necessary. So I'm starting here and working my way outwards.</p>
|
|
||||||
<p>Leave any comments, feedback and suggestions on <a href="http://reddit.com/r/dicecloud">this subreddit</a>. If you've never used reddit before, all you need is a username and password to sign up. So it should be pretty accessible.</p>
|
|
||||||
<p>If you'd like to see a list of known issues and upcoming features, check out the <a href="https://trello.com/b/94M0SCnq/dicecloud-roadmap">DiceCloud Roadmap</a>.</p>
|
|
||||||
<h2>Character Sheet Philosophy</h2>
|
<h2>Character Sheet Philosophy</h2>
|
||||||
<p>Setting up your character on Dicecloud is going to take you a little longer than just filling it in on a paper character sheet would have. The goal of using an online sheet is to make actually playing the game more streamlined, and ultimately more fun. So putting a little extra effort into setting up your character now will pay off over and over again once you're playing.</p>
|
<p>Setting up your character on Dicecloud is going to take you a little longer than just filling it in on a paper character sheet would have. The goal of using an online sheet is to make actually playing the game more streamlined, and ultimately more fun. So putting a little extra effort into setting up your character now will pay off over and over again once you're playing.</p>
|
||||||
<p>The idea is to track where each number comes from, and allow you to easily make changes on the fly.</p>
|
<p>The idea is to track where each number comes from, and allow you to easily make changes on the fly.</p>
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
<template name="home">
|
<template name="home">
|
||||||
<core-toolbar class="blue-grey white-text">
|
<core-toolbar class="app-grey white-text">
|
||||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
<div flex>
|
<div flex>
|
||||||
DiceCloud
|
Home
|
||||||
</div>
|
</div>
|
||||||
</core-toolbar>
|
</core-toolbar>
|
||||||
<div class="scroll-y" style="padding: 16px" fit>
|
{{> intro}}
|
||||||
{{> guide}}
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
@@ -1,25 +1,15 @@
|
|||||||
Template.home.helpers({
|
Template.home.helpers({
|
||||||
characterDetails: function(){
|
selectedTab: function(){
|
||||||
var char = Characters.findOne(
|
return Session.get("homePage.selectedTab");
|
||||||
this._id,
|
},
|
||||||
{fields: {name: 1, gender: 1, alignment: 1, race:1}}
|
|
||||||
);
|
|
||||||
char.title = char.name;
|
|
||||||
char.field = "base";
|
|
||||||
char.color = "d";
|
|
||||||
char.class = "characterCard";
|
|
||||||
return char;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.home.events({
|
Template.home.events({
|
||||||
"tap .characterCard": function(event, instance){
|
"core-animated-pages-transition-end .tabPages": function(event) {
|
||||||
Router.go("characterSheet", {_id: this._id});
|
event.stopPropagation();
|
||||||
},
|
},
|
||||||
"tap #addCharacter": function(event, template) {
|
"tap .homeTabs paper-tab": function(event, instance){
|
||||||
Characters.insert({owner: Meteor.userId()});
|
Session.set("homePage.selectedTab",
|
||||||
},
|
event.currentTarget.getAttribute("name"));
|
||||||
"tap #deleteChar": function(event, template){
|
|
||||||
Characters.remove(this._id);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
89
rpg-docs/client/views/home/intro/intro.html
Normal file
89
rpg-docs/client/views/home/intro/intro.html
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<template name="intro">
|
||||||
|
<div class="intro">
|
||||||
|
<div class="section white-text" style="background: #282828">
|
||||||
|
<div class="display2">
|
||||||
|
Dice Cloud
|
||||||
|
</div>
|
||||||
|
<img style="width:130px; height:130px; background-color: #282828;"
|
||||||
|
src="/crown-dice-logo-cropped-transparent.png">
|
||||||
|
<div class="display1">
|
||||||
|
Unofficial Online Realtime D&D 5e App
|
||||||
|
</div>
|
||||||
|
<h2>
|
||||||
|
Spend less time shuffling paper and more time playing the game
|
||||||
|
</h2>
|
||||||
|
{{#unless currentUser}}
|
||||||
|
<div layout horizontal around-justified wrap>
|
||||||
|
<paper-button class="red white-text signInButton"
|
||||||
|
style="margin: 16px;"
|
||||||
|
raised>
|
||||||
|
Sign In
|
||||||
|
</paper-button>
|
||||||
|
<paper-button class="red white-text signUpButton"
|
||||||
|
style="margin: 16px;"
|
||||||
|
raised>
|
||||||
|
Sign Up
|
||||||
|
</paper-button>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div style="padding-bottom: 0;"></div>
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
<div class="section" style="background-color: #e9e9e9;">
|
||||||
|
<div>
|
||||||
|
<div class="display1">Character Sheet Open Beta</div>
|
||||||
|
<h2 style="margin-bottom: 16px;">
|
||||||
|
Check out the example characters
|
||||||
|
</h2>
|
||||||
|
<div layout horizontal around-justified wrap>
|
||||||
|
<paper-shadow class="card characterCard ssArcher clickable"
|
||||||
|
z="2">
|
||||||
|
<div class="top subhead green white-text">
|
||||||
|
<div class="subhead" flex>
|
||||||
|
Starter Set Archer
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bottom text">Lawful Good Human</div>
|
||||||
|
</paper-shadow>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section white-text" style="background: #282828">
|
||||||
|
<div class="columns" layout horizontal around-justified wrap>
|
||||||
|
<div>
|
||||||
|
<h1>Check out the guide</h1>
|
||||||
|
<p>
|
||||||
|
Learn how your class gives you features, those features have effects,
|
||||||
|
and those effects determine your stats.
|
||||||
|
<paper-button class="guideButton">View Guide</paper-button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1>
|
||||||
|
Discuss
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
On the official subreddit
|
||||||
|
<paper-button class="redditButton">
|
||||||
|
<a href="http://www.reddit.com/r/dicecloud/">
|
||||||
|
/r/dicecloud
|
||||||
|
</a>
|
||||||
|
</paper-button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1>
|
||||||
|
Get involved
|
||||||
|
</h1>
|
||||||
|
<p>Shape upcoming features and track bugs on the Dice Cloud Trello board
|
||||||
|
<paper-button class="trelloButton">
|
||||||
|
<a href="https://trello.com/b/94M0SCnq/dicecloud-roadmap">
|
||||||
|
Trello Roadmap
|
||||||
|
</a>
|
||||||
|
</paper-button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
14
rpg-docs/client/views/home/intro/intro.js
Normal file
14
rpg-docs/client/views/home/intro/intro.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Template.intro.events({
|
||||||
|
"tap .signInButton": function() {
|
||||||
|
Router.go("/sign-in");
|
||||||
|
},
|
||||||
|
"tap .signUpButton": function() {
|
||||||
|
Router.go("/sign-up");
|
||||||
|
},
|
||||||
|
"tap .ssArcher": function() {
|
||||||
|
Router.go("/character/yBWwt5XQTTHZiRQxq");
|
||||||
|
},
|
||||||
|
"tap .guideButton": function() {
|
||||||
|
Router.go("/guide");
|
||||||
|
},
|
||||||
|
});
|
||||||
33
rpg-docs/client/views/home/intro/intro.scss
Normal file
33
rpg-docs/client/views/home/intro/intro.scss
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
.intro {
|
||||||
|
.section {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 200px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-top: 24px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
& > div, & > h2 {
|
||||||
|
padding: 32px;
|
||||||
|
.display1 {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.columns > div{
|
||||||
|
max-width: 300px;
|
||||||
|
padding: 16px;
|
||||||
|
text-align: center;
|
||||||
|
paper-button {
|
||||||
|
color: #FF5252;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paper-button {
|
||||||
|
min-width: 200px;
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<link rel="import" href="/components/core-icons/editor-icons.html">
|
<link rel="import" href="/components/core-icons/editor-icons.html">
|
||||||
<link rel="import" href="/components/core-icons/image-icons.html">
|
<link rel="import" href="/components/core-icons/image-icons.html">
|
||||||
<link rel="import" href="/components/core-icons/social-icons.html">
|
<link rel="import" href="/components/core-icons/social-icons.html">
|
||||||
|
<link rel="import" href="/components/core-image/core-image.html">
|
||||||
<link rel="import" href="/components/core-item/core-item.html">
|
<link rel="import" href="/components/core-item/core-item.html">
|
||||||
<link rel="import" href="/components/core-menu/core-menu.html">
|
<link rel="import" href="/components/core-menu/core-menu.html">
|
||||||
<link rel="import" href="/components/core-scaffold/core-scaffold.html">
|
<link rel="import" href="/components/core-scaffold/core-scaffold.html">
|
||||||
@@ -32,11 +33,12 @@
|
|||||||
<link rel="import" href="/components/paper-radio-group/paper-radio-group.html">
|
<link rel="import" href="/components/paper-radio-group/paper-radio-group.html">
|
||||||
<link rel="import" href="/components/paper-shadow/paper-shadow.html">
|
<link rel="import" href="/components/paper-shadow/paper-shadow.html">
|
||||||
<link rel="import" href="/components/paper-spinner/paper-spinner.html">
|
<link rel="import" href="/components/paper-spinner/paper-spinner.html">
|
||||||
|
<link rel="import" href="/components/paper-slider/paper-slider.html">
|
||||||
<link rel="import" href="/components/paper-tabs/paper-tabs.html">
|
<link rel="import" href="/components/paper-tabs/paper-tabs.html">
|
||||||
<link rel="import" href="/components/paper-toast/paper-toast.html">
|
<link rel="import" href="/components/paper-toast/paper-toast.html">
|
||||||
<link rel="import" href="/components/paper-toggle-button/paper-toggle-button.html">
|
<link rel="import" href="/components/paper-toggle-button/paper-toggle-button.html">
|
||||||
|
|
||||||
<!--custom components-->
|
<!--custom components-->
|
||||||
<link rel="import" href="/custom_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
<link rel="import" href="/custom_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||||
<link rel="import" href="/custom_components/paper-slider-diff/paper-slider.html">
|
<link rel="import" href="/custom_components/paper-diff-slider/paper-diff-slider.html">
|
||||||
<link rel="import" href="/custom_components/swipe-detect/swipe-detect.html">
|
<link rel="import" href="/custom_components/swipe-detect/swipe-detect.html">
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
<core-header-panel drawer navigation flex mode="seamed" class="white">
|
<core-header-panel drawer navigation flex mode="seamed" class="white">
|
||||||
<div id="accountSummary">
|
<div id="accountSummary">
|
||||||
{{#if currentUser}}
|
{{#if currentUser}}
|
||||||
<div id="profileLink" style="text-decoration: underline; cursor: pointer;">
|
<div id="profileLink"
|
||||||
|
style="text-decoration: underline; cursor: pointer; font-size: 16px;">
|
||||||
{{profileLink}}
|
{{profileLink}}
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
<div id="navPanel">
|
<div id="navPanel">
|
||||||
<core-item id="homeNav" icon="home" label="Home"></core-item>
|
<core-item id="homeNav" icon="home" label="Home"></core-item>
|
||||||
{{> characterSideList}}
|
{{> characterSideList}}
|
||||||
|
<core-item id="guide" icon="social:school" label="Guide"></core-item>
|
||||||
<core-item id="feedback" icon="bug-report" label="Send Feedback"></core-item>
|
<core-item id="feedback" icon="bug-report" label="Send Feedback"></core-item>
|
||||||
<core-item id="changeLog" icon="list" label="Change Log"></core-item>
|
<core-item id="changeLog" icon="list" label="Change Log"></core-item>
|
||||||
</div>
|
</div>
|
||||||
@@ -23,7 +25,7 @@
|
|||||||
transitions="hero-transition cross-fade"
|
transitions="hero-transition cross-fade"
|
||||||
selected={{globalDetailSelected}}>
|
selected={{globalDetailSelected}}>
|
||||||
<section id="mainContentSection" class={{notSelected}}>
|
<section id="mainContentSection" class={{notSelected}}>
|
||||||
<core-header-panel fit mode="seamed">
|
<core-header-panel fit mode="standard">
|
||||||
{{> yield}}
|
{{> yield}}
|
||||||
</core-header-panel>
|
</core-header-panel>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -41,4 +41,8 @@ Template.layout.events({
|
|||||||
Router.go("changeLog");
|
Router.go("changeLog");
|
||||||
instance.find("core-drawer-panel").closeDrawer();
|
instance.find("core-drawer-panel").closeDrawer();
|
||||||
},
|
},
|
||||||
|
"tap #guide": function(event, instance) {
|
||||||
|
Router.go("guide");
|
||||||
|
instance.find("core-drawer-panel").closeDrawer();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
.bigSpinner {
|
.bigSpinner {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template name="loading">
|
<template name="loading">
|
||||||
<core-toolbar class="blue-grey white-text">
|
<core-toolbar class="app-grey white-text">
|
||||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
</core-toolbar>
|
</core-toolbar>
|
||||||
<div fit layout vertical center center-justified>
|
<div fit layout vertical center center-justified>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template name="changeLog">
|
<template name="changeLog">
|
||||||
<core-toolbar class="blue-grey white-text">
|
<core-toolbar class="app-grey white-text">
|
||||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
<div flex>
|
<div flex>
|
||||||
Change Log
|
Change Log
|
||||||
|
|||||||
@@ -13,22 +13,22 @@
|
|||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
aria-label="Delete Feature"
|
aria-label="Delete Feature">
|
||||||
noink></paper-icon-button>
|
</paper-icon-button>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
{{#unless hideColor}}
|
{{#unless hideColor}}
|
||||||
{{> colorDropdown}}
|
{{> colorDropdown}}
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
<paper-icon-button id="doneEditingButton"
|
<paper-icon-button id="doneEditingButton"
|
||||||
icon="done"
|
icon="done"
|
||||||
aria-label="Delete Feature"
|
aria-label="Delete Feature">
|
||||||
noink></paper-icon-button>
|
</paper-icon-button>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if showEdit}}
|
{{#if showEdit}}
|
||||||
<paper-icon-button id="editButton"
|
<paper-icon-button id="editButton"
|
||||||
icon="create"
|
icon="create"
|
||||||
aria-label="Delete Feature"
|
aria-label="Delete Feature">
|
||||||
noink></paper-icon-button>
|
</paper-icon-button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,19 +9,11 @@ Template.baseDialog.onRendered(function(){
|
|||||||
|
|
||||||
Template.baseDialog.helpers({
|
Template.baseDialog.helpers({
|
||||||
editing: function(){
|
editing: function(){
|
||||||
return Template.instance().editing.get();
|
return Template.instance().editing.get() && canEditCharacter(Template.parentData().charId);
|
||||||
},
|
},
|
||||||
showEdit: function() {
|
showEdit: function() {
|
||||||
if (this.hideEdit) return false;
|
if (this.hideEdit) return false;
|
||||||
var charId = Template.parentData().charId;
|
return canEditCharacter(Template.parentData().charId);
|
||||||
if (charId){
|
|
||||||
var char = Characters.findOne(charId);
|
|
||||||
var userId = Meteor.userId();
|
|
||||||
if (char && userId)
|
|
||||||
return char.owner === userId ||
|
|
||||||
_.contains(char.writers, userId);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template name="titledAtForm">
|
<template name="titledAtForm">
|
||||||
<core-toolbar class="blue-grey white-text">
|
<core-toolbar class="app-grey white-text">
|
||||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
<div flex>
|
<div flex>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
//evaluates a calculation string
|
//evaluates a calculation string
|
||||||
evaluate = function(charId, 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){
|
string = string.replace(/\b[a-z]+\b/gi, function(sub){
|
||||||
//fields
|
//fields
|
||||||
if (Schemas.Character.schema(sub)){
|
if (Schemas.Character.schema(sub)){
|
||||||
return char.fieldValue(sub);
|
return Characters.calculate.fieldValue(charId, sub);
|
||||||
}
|
}
|
||||||
//ability modifiers
|
//ability modifiers
|
||||||
var abilityMods = [
|
var abilityMods = [
|
||||||
@@ -19,7 +18,7 @@ evaluate = function(charId, string){
|
|||||||
if (_.contains(abilityMods, sub)){
|
if (_.contains(abilityMods, sub)){
|
||||||
var slice = sub.slice(0, -3);
|
var slice = sub.slice(0, -3);
|
||||||
try {
|
try {
|
||||||
return char.abilityMod(slice);
|
return Characters.calculate.abilityMod(charId, slice);
|
||||||
} catch (e){
|
} catch (e){
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
@@ -33,7 +32,7 @@ evaluate = function(charId, string){
|
|||||||
}
|
}
|
||||||
//character level
|
//character level
|
||||||
if (sub.toUpperCase() === "LEVEL"){
|
if (sub.toUpperCase() === "LEVEL"){
|
||||||
return char.level();
|
return Characters.calculate.level(charId);
|
||||||
}
|
}
|
||||||
return sub;
|
return sub;
|
||||||
});
|
});
|
||||||
@@ -41,7 +40,6 @@ evaluate = function(charId, string){
|
|||||||
var result = math.eval(string);
|
var result = math.eval(string);
|
||||||
return result;
|
return result;
|
||||||
} catch (e){
|
} catch (e){
|
||||||
console.log("Failed to evaluate ", string);
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
preventLoop = function(inputFunction){
|
preventLoop = function(inputFunction){
|
||||||
|
var self = this;
|
||||||
if (!_.isFunction(inputFunction)){
|
if (!_.isFunction(inputFunction)){
|
||||||
throw new Meteor.Error(
|
throw new Meteor.Error(
|
||||||
"Not a function",
|
"Not a function",
|
||||||
@@ -9,23 +10,26 @@ preventLoop = function(inputFunction){
|
|||||||
//if we try to visit the same argument twice before resolving its value
|
//if we try to visit the same argument twice before resolving its value
|
||||||
//we are in a dependency loop and need to GTFO
|
//we are in a dependency loop and need to GTFO
|
||||||
var visitedArgs = [];
|
var visitedArgs = [];
|
||||||
return function(argument){
|
return function(){
|
||||||
var value;
|
var result;
|
||||||
|
var hash = _.reduce(arguments, function(memo, arg) {
|
||||||
|
return memo + arg;
|
||||||
|
}, "");
|
||||||
//we're still evaluating this attribute, must be in a loop
|
//we're still evaluating this attribute, must be in a loop
|
||||||
if (_.contains(visitedArgs, argument)) {
|
if (_.contains(visitedArgs, hash)) {
|
||||||
console.warn("dependency loop detected");
|
console.warn("dependency loop detected");
|
||||||
return NaN;
|
return NaN;
|
||||||
} else {
|
} else {
|
||||||
//push this skill to the list of visited skills
|
//push this hash to the list of visited hashes
|
||||||
//we can't visit it again unless it returns first
|
//we can't visit it again unless it returns first
|
||||||
visitedArgs.push(argument);
|
visitedArgs.push(hash);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
value = inputFunction.call(this, argument);
|
result = inputFunction.apply(this, arguments);
|
||||||
} finally{
|
} finally{
|
||||||
//this argument returns or fails, pull it from the array
|
//this hash returns or fails, pull it from the array
|
||||||
visitedArgs = _.without(visitedArgs, argument);
|
visitedArgs = _.without(visitedArgs, hash);
|
||||||
}
|
}
|
||||||
return value;
|
return result;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
60
rpg-docs/lib/memoize/memoize.js
Normal file
60
rpg-docs/lib/memoize/memoize.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
Tracker.memoize = function(func, hasher){
|
||||||
|
var memoize = function(key) {
|
||||||
|
var cache = memoize.cache;
|
||||||
|
var address = "" + (hasher ? hasher.apply(this, arguments) : key);
|
||||||
|
if (!_.has(cache, address)) {
|
||||||
|
cache[address] = new CacheObject(func, address, arguments, cache, this);
|
||||||
|
}
|
||||||
|
return cache[address].get();
|
||||||
|
};
|
||||||
|
memoize.cache = {};
|
||||||
|
return memoize;
|
||||||
|
};
|
||||||
|
|
||||||
|
function CacheObject(func, address, args, cache, context){
|
||||||
|
var self = this;
|
||||||
|
self.currentValue = null;
|
||||||
|
self.dep = new Tracker.Dependency();
|
||||||
|
self.numRun = 0;
|
||||||
|
|
||||||
|
//spawn a new autorun that keeps the value up-to-date
|
||||||
|
Tracker.nonreactive(function() {
|
||||||
|
Tracker.autorun(function(computation) {
|
||||||
|
//if this isn't the first run and nobody is listening,
|
||||||
|
//delete itself from cache and stop the computation
|
||||||
|
if (!computation.firstRun && !self.dep.hasDependents()){
|
||||||
|
computation.stop();
|
||||||
|
delete cache[address];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//if we haven't run this before this flush, reset the counter after the flush
|
||||||
|
if(self.numRun === 0){
|
||||||
|
Tracker.afterFlush(function(){
|
||||||
|
self.numRun = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.numRun++;
|
||||||
|
//call the expensive function
|
||||||
|
//even if we don't use its value, we need to track its dependencies
|
||||||
|
var newValue = func.apply(context, args);
|
||||||
|
//prevent dependency loops, the memoized function shouldn't re-run
|
||||||
|
//more than once per flush
|
||||||
|
if (self.numRun > 1){
|
||||||
|
newValue = NaN;
|
||||||
|
if(_.isNaN(self.currentValue)) return;
|
||||||
|
}
|
||||||
|
//if the value changed, store the new value
|
||||||
|
if (self.currentValue !== newValue){
|
||||||
|
self.currentValue = newValue;
|
||||||
|
//tell the dependents that we've changed
|
||||||
|
self.dep.changed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheObject.prototype.get = function() {
|
||||||
|
//if there is an active computation, track dependents
|
||||||
|
if (Tracker.active) this.dep.depend();
|
||||||
|
return this.currentValue;
|
||||||
|
};
|
||||||
@@ -98,9 +98,9 @@ trackEncumbranceConditions = function(charId, templateInstance) {
|
|||||||
});
|
});
|
||||||
var character = Characters.findOne(
|
var character = Characters.findOne(
|
||||||
charId,
|
charId,
|
||||||
{fields: {strength: 1, "settings": 1}}
|
{fields: {"settings": 1}}
|
||||||
);
|
);
|
||||||
var strength = character.attributeValue("strength");
|
var strength = Characters.calculate.attributeValue(charId, "strength");
|
||||||
var give = function(condition) {
|
var give = function(condition) {
|
||||||
Meteor.call("giveCondition", charId, condition);
|
Meteor.call("giveCondition", charId, condition);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ ChangeLogs.insert({
|
|||||||
});
|
});
|
||||||
|
|
||||||
ChangeLogs.insert({
|
ChangeLogs.insert({
|
||||||
version: "0.5.2",
|
version: "0.5.3",
|
||||||
changes: [
|
changes: [
|
||||||
"Prevented a harmless error caused by effects which have no stat set",
|
"Prevented a harmless error caused by effects which have no stat set",
|
||||||
"Added the ability to hide the spells tab",
|
"Added the ability to hide the spells tab",
|
||||||
@@ -144,3 +144,94 @@ ChangeLogs.insert({
|
|||||||
"Overhauled how effects' stats are chosen",
|
"Overhauled how effects' stats are chosen",
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.5.4",
|
||||||
|
changes: [
|
||||||
|
"Fixed rounding error on net worth calculation",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.5.5",
|
||||||
|
changes: [
|
||||||
|
"Fixed reports from google users not correctly storing the reply-to email address",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.5.6",
|
||||||
|
changes: [
|
||||||
|
"Changed front page",
|
||||||
|
"Moved to a darker style",
|
||||||
|
"Added support for letting characters be viewed by \"anyone with the link\"",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.5.7",
|
||||||
|
changes: [
|
||||||
|
"Added proficiencies to backgrounds",
|
||||||
|
"Added attacks to spells",
|
||||||
|
"Added a move item dialog to mobile devices, but it can't be accessed yet, because long-presses are broken",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.6.0",
|
||||||
|
changes: [
|
||||||
|
"Big performance improvements: loading characters that you've viewed recently and changing effects on characters should be much faster",
|
||||||
|
"Spell dialogs no longer show their casting time, range, etc. if those fields aren't filled in",
|
||||||
|
"The settings dialog now has a done button so it can be closed on small devices",
|
||||||
|
"Container dialogs now have the weight summaries rounded down properly",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.6.1",
|
||||||
|
changes: [
|
||||||
|
"Experience dialogs should update their edit-mode inputs properly now",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.6.2",
|
||||||
|
changes: [
|
||||||
|
"Fixed a regression which broke min and max effects",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.6.3",
|
||||||
|
changes: [
|
||||||
|
"Fixed a regression that stopped skills and attributes from rounding down correctly",
|
||||||
|
"Made dependency loops return NaN immediately, rather than looping indefinitely until a page refresh. Adding an effect that adds \"strength\" to Strength, won't cause Strength to constantly increase or freeze the browser, Strength just becomes NaN",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.6.4",
|
||||||
|
changes: [
|
||||||
|
"Hit dice now has a \"+\" between the dice and the constitution modifier",
|
||||||
|
"Items with multiple attacks should have the damage type editable on all attacks now",
|
||||||
|
"Spell attacks should now correctly inherit changes to their spell's name",
|
||||||
|
"Character lists should now be ordered alphabetically",
|
||||||
|
"Skills should have correct min and max effects applied again",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.6.5",
|
||||||
|
changes: [
|
||||||
|
"Net worth now takes container values into account",
|
||||||
|
"Added support for character pictures",
|
||||||
|
"Disabled edit buttons for read-only viewers",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ChangeLogs.insert({
|
||||||
|
version: "0.6.6",
|
||||||
|
changes: [
|
||||||
|
"Text fields now accept github-flavor markdown formatting",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|||||||
BIN
rpg-docs/public/crown-dice-logo-cropped-transparent.png
Normal file
BIN
rpg-docs/public/crown-dice-logo-cropped-transparent.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -8,55 +8,55 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
`paper-slider` allows user to select a value from a range of values by
|
`paper-diff-slider` allows user to select a value from a range of values by
|
||||||
moving the slider thumb. The interactive nature of the slider makes it a
|
moving the slider thumb. The interactive nature of the slider makes it a
|
||||||
great choice for settings that reflect intensity levels, such as volume,
|
great choice for settings that reflect intensity levels, such as volume,
|
||||||
brightness, or color saturation.
|
brightness, or color saturation.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
<paper-slider></paper-slider>
|
<paper-diff-slider></paper-diff-slider>
|
||||||
|
|
||||||
Use `min` and `max` to specify the slider range. Default is 0 to 100.
|
Use `min` and `max` to specify the slider range. Default is 0 to 100.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
<paper-slider min="10" max="200" value="110"></paper-slider>
|
<paper-diff-slider min="10" max="200" value="110"></paper-diff-slider>
|
||||||
|
|
||||||
Styling slider:
|
Styling slider:
|
||||||
|
|
||||||
To change the slider progress bar color:
|
To change the slider progress bar color:
|
||||||
|
|
||||||
paper-slider::shadow #sliderBar::shadow #activeProgress {
|
paper-diff-slider::shadow #sliderBar::shadow #activeProgress {
|
||||||
background-color: #0f9d58;
|
background-color: #0f9d58;
|
||||||
}
|
}
|
||||||
|
|
||||||
To change the slider knob color:
|
To change the slider knob color:
|
||||||
|
|
||||||
paper-slider::shadow #sliderKnobInner {
|
paper-diff-slider::shadow #sliderKnobInner {
|
||||||
background-color: #0f9d58;
|
background-color: #0f9d58;
|
||||||
}
|
}
|
||||||
|
|
||||||
To change the slider pin color:
|
To change the slider pin color:
|
||||||
|
|
||||||
paper-slider::shadow #sliderKnobInner::before {
|
paper-diff-slider::shadow #sliderKnobInner::before {
|
||||||
background-color: #0f9d58;
|
background-color: #0f9d58;
|
||||||
}
|
}
|
||||||
|
|
||||||
To change the slider pin's font color:
|
To change the slider pin's font color:
|
||||||
|
|
||||||
paper-slider::shadow #sliderKnob > #sliderKnobInner::after {
|
paper-diff-slider::shadow #sliderKnob > #sliderKnobInner::after {
|
||||||
color: #0f9d58
|
color: #0f9d58
|
||||||
}
|
}
|
||||||
|
|
||||||
To change the slider secondary progress bar color:
|
To change the slider secondary progress bar color:
|
||||||
|
|
||||||
paper-slider::shadow #sliderBar::shadow #secondaryProgress {
|
paper-diff-slider::shadow #sliderBar::shadow #secondaryProgress {
|
||||||
background-color: #0f9d58;
|
background-color: #0f9d58;
|
||||||
}
|
}
|
||||||
|
|
||||||
@group Paper Elements
|
@group Paper Elements
|
||||||
@element paper-slider
|
@element paper-diff-slider
|
||||||
@extends core-range
|
@extends core-range
|
||||||
@homepage github.io
|
@homepage github.io
|
||||||
-->
|
-->
|
||||||
@@ -65,10 +65,10 @@ To change the slider secondary progress bar color:
|
|||||||
<link rel="import" href="../../components/paper-progress/paper-progress.html">
|
<link rel="import" href="../../components/paper-progress/paper-progress.html">
|
||||||
<link rel="import" href="../../components/paper-input/paper-input.html">
|
<link rel="import" href="../../components/paper-input/paper-input.html">
|
||||||
|
|
||||||
<polymer-element name="paper-slider" extends="core-range" attributes="snaps pin disabled secondaryProgress editable immediateValue" role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100">
|
<polymer-element name="paper-diff-slider" extends="core-range" attributes="snaps pin disabled secondaryProgress editable immediateValue" role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100">
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<link rel="stylesheet" href="paper-slider.css">
|
<link rel="stylesheet" href="paper-diff-slider.css">
|
||||||
|
|
||||||
<template if="{{!disabled}}">
|
<template if="{{!disabled}}">
|
||||||
<core-a11y-keys target="{{}}" keys="left down pagedown home" on-keys-pressed="{{decrementKey}}"></core-a11y-keys>
|
<core-a11y-keys target="{{}}" keys="left down pagedown home" on-keys-pressed="{{decrementKey}}"></core-a11y-keys>
|
||||||
@@ -109,7 +109,7 @@ To change the slider secondary progress bar color:
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
Polymer('paper-slider', {
|
Polymer('paper-diff-slider', {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired when the slider's value changes.
|
* Fired when the slider's value changes.
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 60 KiB |
@@ -1,12 +1,12 @@
|
|||||||
Meteor.publish("singleCharacter", function(characterId){
|
Meteor.publish("singleCharacter", function(characterId){
|
||||||
userId = this.userId;
|
userId = this.userId;
|
||||||
if (!userId) return [];
|
|
||||||
var char = Characters.findOne({
|
var char = Characters.findOne({
|
||||||
_id: characterId,
|
_id: characterId,
|
||||||
$or: [
|
$or: [
|
||||||
{readers: userId},
|
{readers: userId},
|
||||||
{writers: userId},
|
{writers: userId},
|
||||||
{owner: userId},
|
{owner: userId},
|
||||||
|
{"settings.viewPermission": "public"},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
if (char){
|
if (char){
|
||||||
|
|||||||
Reference in New Issue
Block a user