Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f60766d5d | ||
|
|
e992aeebef | ||
|
|
4108346a98 | ||
|
|
946fadadc2 | ||
|
|
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 | ||
|
|
4f1376a666 | ||
|
|
78b1d71b9d | ||
|
|
1323d8006c | ||
|
|
87d722adaf | ||
|
|
90e511eb00 | ||
|
|
5b8c25f5de | ||
|
|
2fbc54fee8 | ||
|
|
a064ae3fe8 | ||
|
|
ba9b518d7e | ||
|
|
2f729070b2 | ||
|
|
7aedb9451c | ||
|
|
c6886dd49e | ||
|
|
038ce490e4 | ||
|
|
52bef57637 | ||
|
|
29e9f8c8dc | ||
|
|
fea02811ff | ||
|
|
73cee52fff | ||
|
|
b58c006ed4 | ||
|
|
ef44f6c1a5 | ||
|
|
f455cea43f | ||
|
|
e4083bc744 | ||
|
|
baffafb62a | ||
|
|
4143929667 | ||
|
|
18286d1b9c | ||
|
|
9f51567162 | ||
|
|
66d8a3bfbf | ||
|
|
a9648c10cc | ||
|
|
679292373c | ||
|
|
ae416458b5 | ||
|
|
0ff4a887ea | ||
|
|
955794b5c0 | ||
|
|
b0ac1dcc29 | ||
|
|
83150bc527 | ||
|
|
061f1fd0a5 | ||
|
|
e40dd196e6 | ||
|
|
5dbb59ef80 | ||
|
|
49e25d7304 | ||
|
|
85df0257e2 | ||
|
|
b88bb95928 | ||
|
|
2122e543d5 | ||
|
|
a71519aaa7 |
@@ -16,7 +16,6 @@ differential:vulcanize
|
||||
matb33:collection-hooks
|
||||
zimme:collection-softremovable
|
||||
momentjs:moment
|
||||
mike:mocha
|
||||
dburles:mongo-collection-instances
|
||||
percolate:migrations
|
||||
ecwyne:mathjs
|
||||
@@ -24,3 +23,7 @@ useraccounts:polymer
|
||||
accounts-google
|
||||
splendido:accounts-meld
|
||||
email
|
||||
fourseven:scss@2.1.1
|
||||
wolves:bourbon
|
||||
meteorhacks:subs-manager
|
||||
meteorhacks:kadira
|
||||
|
||||
@@ -6,7 +6,6 @@ accounts-ui@1.1.5
|
||||
accounts-ui-unstyled@1.1.7
|
||||
aldeed:collection2@2.3.3
|
||||
aldeed:simple-schema@1.3.3
|
||||
amplify@1.0.0
|
||||
autoupdate@1.2.1
|
||||
base64@1.0.3
|
||||
binary-heap@1.0.3
|
||||
@@ -25,6 +24,7 @@ ecwyne:mathjs@0.25.0
|
||||
ejson@1.0.6
|
||||
email@1.0.6
|
||||
fastclick@1.0.3
|
||||
fourseven:scss@2.1.1
|
||||
geojson-utils@1.0.3
|
||||
google@1.1.5
|
||||
html-tools@1.0.4
|
||||
@@ -50,30 +50,27 @@ logging@1.0.7
|
||||
matb33:collection-hooks@0.7.13
|
||||
meteor@1.1.6
|
||||
meteor-platform@1.2.2
|
||||
mike:mocha@0.5.4
|
||||
meteorhacks:kadira@2.21.0
|
||||
meteorhacks:meteorx@1.3.1
|
||||
meteorhacks:subs-manager@1.3.0
|
||||
minifiers@1.1.5
|
||||
minimongo@1.0.8
|
||||
mobile-status-bar@1.0.3
|
||||
momentjs:moment@2.10.3
|
||||
mongo@1.1.0
|
||||
mongo-livedata@1.0.8
|
||||
npm-bcrypt@0.7.8_2
|
||||
oauth@1.1.4
|
||||
oauth2@1.1.3
|
||||
observe-sequence@1.0.6
|
||||
ordered-dict@1.0.3
|
||||
package-version-parser@3.0.3
|
||||
percolate:migrations@0.7.5
|
||||
practicalmeteor:chai@1.9.2_3
|
||||
practicalmeteor:loglevel@1.1.0_3
|
||||
random@1.0.3
|
||||
reactive-dict@1.1.0
|
||||
reactive-var@1.0.5
|
||||
reload@1.1.3
|
||||
retry@1.0.3
|
||||
routepolicy@1.0.5
|
||||
sanjo:long-running-child-process@1.0.3
|
||||
sanjo:meteor-files-helpers@1.1.0_4
|
||||
sanjo:meteor-version@1.0.0
|
||||
service-configuration@1.0.4
|
||||
session@1.1.0
|
||||
sha@1.0.3
|
||||
@@ -90,12 +87,8 @@ underscore@1.0.3
|
||||
url@1.0.4
|
||||
useraccounts:core@1.9.1
|
||||
useraccounts:polymer@1.9.1
|
||||
velocity:chokidar@0.12.6_1
|
||||
velocity:core@0.6.1
|
||||
velocity:html-reporter@0.5.3
|
||||
velocity:meteor-internals@1.1.0_7
|
||||
velocity:shim@0.1.0
|
||||
webapp@1.2.0
|
||||
webapp-hashing@1.0.3
|
||||
wolves:bourbon@1.0.0
|
||||
zimme:collection-behaviours@1.0.4
|
||||
zimme:collection-softremovable@1.0.4
|
||||
|
||||
@@ -24,18 +24,12 @@ Schemas.Attack = new SimpleSchema({
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
damageBonus: {
|
||||
damage: {
|
||||
type: String,
|
||||
defaultValue: "strengthMod",
|
||||
defaultValue: "1d8 + {strengthMod}",
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
damageDice: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: "1d8",
|
||||
allowedValues: DAMAGE_DICE,
|
||||
},
|
||||
damageType: {
|
||||
type: String,
|
||||
allowedValues: [
|
||||
|
||||
@@ -1,28 +1,51 @@
|
||||
Buffs = new Mongo.Collection("buffs");
|
||||
|
||||
//buffs are temporary once applied and store things which expire and their expiry time
|
||||
Schemas.Buff = new SimpleSchema({
|
||||
//buff id
|
||||
_id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
autoValue: function(){
|
||||
if (!this.isSet) return Random.id();
|
||||
},
|
||||
},
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
//expiry time
|
||||
expiry: {type: Number, optional: true},
|
||||
duration: {type: Number},
|
||||
name: {
|
||||
type: String,
|
||||
trim: false,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
allowedValues: [
|
||||
"inate",
|
||||
"custom",
|
||||
],
|
||||
},
|
||||
"lifeTime.total": {
|
||||
type: Number,
|
||||
defaultValue: 0, //0 is infinite
|
||||
min: 0,
|
||||
},
|
||||
"lifeTime.spent": {
|
||||
type: Number,
|
||||
defaultValue: 0,
|
||||
min: 0,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
});
|
||||
|
||||
Buffs.attachSchema(Schemas.Buff);
|
||||
|
||||
Buffs.attachBehaviour("softRemovable");
|
||||
makeParent(Buffs, "name"); //parents of effects and attacks
|
||||
makeParent(Buffs, ["name", "enabled"]); //parents of effects
|
||||
|
||||
Buffs.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Buffs.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -3,16 +3,16 @@ Characters = new Mongo.Collection("characters");
|
||||
|
||||
Schemas.Character = new SimpleSchema({
|
||||
//strings
|
||||
name: {type: String, defaultValue: "", trim: false},
|
||||
alignment: {type: String, defaultValue: "", trim: false},
|
||||
gender: {type: String, defaultValue: "", trim: false},
|
||||
race: {type: String, defaultValue: "", trim: false},
|
||||
description: {type: String, defaultValue: "", trim: false},
|
||||
personality: {type: String, defaultValue: "", trim: false},
|
||||
ideals: {type: String, defaultValue: "", trim: false},
|
||||
bonds: {type: String, defaultValue: "", trim: false},
|
||||
flaws: {type: String, defaultValue: "", trim: false},
|
||||
backstory: {type: String, defaultValue: "", trim: false},
|
||||
name: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
alignment: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
gender: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
race: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
description: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
personality: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
ideals: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
bonds: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
flaws: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
backstory: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
|
||||
//attributes
|
||||
//ability scores
|
||||
@@ -159,6 +159,7 @@ Schemas.Character = new SimpleSchema({
|
||||
deathSave: {type: Schemas.DeathSave},
|
||||
|
||||
//permissions
|
||||
party: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true},
|
||||
owner: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
|
||||
writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
|
||||
@@ -168,61 +169,122 @@ Schemas.Character = new SimpleSchema({
|
||||
defaultValue: "q",
|
||||
},
|
||||
//TODO add per-character settings
|
||||
"settings.experiencesInc": {type: Number, defaultValue: 20}, //how many experiences to load at a time in XP table
|
||||
//how many experiences to load at a time in XP table
|
||||
"settings.experiencesInc": {type: Number, defaultValue: 20},
|
||||
//slowed down by carrying too much?
|
||||
"settings.useVariantEncumbrance": {type: Boolean, defaultValue: false},
|
||||
"settings.useStandardEncumbrance": {type: Boolean, defaultValue: true},
|
||||
//hide spellcasting
|
||||
"settings.hideSpellcasting": {type: Boolean, defaultValue: false},
|
||||
//show to anyone with link
|
||||
"settings.viewPermission": {
|
||||
type: String,
|
||||
defaultValue: "whitelist",
|
||||
allowedValues: ["whitelist", "public"],
|
||||
},
|
||||
});
|
||||
|
||||
Characters.attachSchema(Schemas.Character);
|
||||
|
||||
var attributeBase = function(charId, statName){
|
||||
check(statName, String);
|
||||
var effects = Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true}
|
||||
).fetch();
|
||||
effects = _.groupBy(effects, "operation");
|
||||
var value = _.contains(DAMAGE_MULTIPLIERS, statName) ? 1 : 0;
|
||||
//if it's a damage multiplier, we treat it specially
|
||||
if (_.contains(DAMAGE_MULTIPLIERS, statName)){
|
||||
var invulnerabilityCount = Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: "mul",
|
||||
value: 0,
|
||||
}).count();
|
||||
if (invulnerabilityCount) return 0;
|
||||
var resistCount = Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: "mul",
|
||||
value: 0.5,
|
||||
}).count();
|
||||
var vulnCount = Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: "mul",
|
||||
value: 2,
|
||||
}).count();
|
||||
if (!resistCount && !vulnCount){
|
||||
return 1;
|
||||
} else if (resistCount && !vulnCount){
|
||||
return 0.5;
|
||||
} else if (!resistCount && vulnCount){
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
var value;
|
||||
var base = 0;
|
||||
var add = 0;
|
||||
var mul = 1;
|
||||
var min = Math.NEGATIVE_INFINITY;
|
||||
var max = Math.POSITIVE_INFINITY;
|
||||
|
||||
//start with the highest base value
|
||||
_.each(effects.base, function(effect){
|
||||
var efv = evaluateEffect(charId, effect);
|
||||
if (efv > value){
|
||||
value = efv;
|
||||
Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||
}).forEach(function(effect) {
|
||||
value = evaluateEffect(charId, effect);
|
||||
if (effect.operation === "base"){
|
||||
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
|
||||
_.each(effects.add, function(effect){
|
||||
value += evaluateEffect(charId, effect);
|
||||
});
|
||||
var result = (base + add) * mul;
|
||||
if (result < min) result = min;
|
||||
if (result > max) result = max;
|
||||
|
||||
//multiply all the mul values
|
||||
_.each(effects.mul, function(effect){
|
||||
value *= evaluateEffect(charId, effect);
|
||||
});
|
||||
|
||||
//ensure value is >= all mins
|
||||
_.each(effects.min, function(effect){
|
||||
var min = evaluateEffect(charId, effect);
|
||||
value = value > min ? value : min;
|
||||
});
|
||||
|
||||
//ensure value is <= all maxes
|
||||
_.each(effects.max, function(effect){
|
||||
var max = evaluateEffect(charId, effect);
|
||||
value = value < max ? value : max;
|
||||
});
|
||||
return value;
|
||||
return result;
|
||||
};
|
||||
|
||||
//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){
|
||||
if (Meteor.isClient) {
|
||||
Template.registerHelper("characterCalculate", function(func, charId, input) {
|
||||
try {
|
||||
return Characters.calculate[func](charId, input);
|
||||
} catch (e){
|
||||
if (!Characters.calculate[func]){
|
||||
throw new Error(func + "is not a function name");
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//create a local memoize with a argument concatenating hash function
|
||||
var memoize = function(f) {
|
||||
return Tracker.memoize(f, function() {
|
||||
return _.reduce(arguments, function(memo, arg) {
|
||||
return memo + arg;
|
||||
}, "");
|
||||
});
|
||||
};
|
||||
|
||||
//memoize funcitons that have finds and slow loops
|
||||
Characters.calculate = {
|
||||
getField: function(charId, fieldName) {
|
||||
var fieldSelector = {};
|
||||
fieldSelector[fieldName] = 1;
|
||||
var char = Characters.findOne(this._id, {fields: fieldSelector});
|
||||
var char = Characters.findOne(charId, {fields: fieldSelector});
|
||||
var field = char[fieldName];
|
||||
if (field === undefined){
|
||||
throw new Meteor.Error(
|
||||
@@ -235,8 +297,7 @@ Characters.helpers({
|
||||
}
|
||||
return field;
|
||||
},
|
||||
//returns the value of a field
|
||||
fieldValue : function(fieldName){
|
||||
fieldValue: function(charId, fieldName) {
|
||||
if (!Schemas.Character.schema(fieldName)){
|
||||
throw new Meteor.Error(
|
||||
"Field not found",
|
||||
@@ -246,102 +307,92 @@ Characters.helpers({
|
||||
//duck typing to get the right value function
|
||||
//.ability implies skill
|
||||
if (Schemas.Character.schema(fieldName + ".ability")){
|
||||
return this.skillMod(fieldName);
|
||||
return Characters.calculate.skillMod(charId, fieldName);
|
||||
}
|
||||
//adjustment implies attribute
|
||||
if (Schemas.Character.schema(fieldName + ".adjustment")){
|
||||
return this.attributeValue(fieldName);
|
||||
return Characters.calculate.attributeValue(charId, fieldName);
|
||||
}
|
||||
//fall back to just returning the field itself
|
||||
return this.getField(fieldName);
|
||||
return Characters.calculate.getField(charId, fieldName);
|
||||
},
|
||||
|
||||
attributeValue: function(attributeName){
|
||||
var charId = this._id;
|
||||
var attribute = this.getField(attributeName);
|
||||
attributeValue: memoize(function(charId, attributeName){
|
||||
var attribute = Characters.calculate.getField(charId, attributeName);
|
||||
//base value
|
||||
var value = this.attributeBase(attributeName);
|
||||
var value = Characters.calculate.attributeBase(charId, attributeName);
|
||||
//plus adjustment
|
||||
value += attribute.adjustment;
|
||||
return value;
|
||||
},
|
||||
|
||||
attributeBase: preventLoop(function(attributeName){
|
||||
var charId = this._id;
|
||||
//base value
|
||||
return attributeBase(charId, attributeName);
|
||||
}),
|
||||
|
||||
skillMod: preventLoop(function(skillName){
|
||||
var charId = this._id;
|
||||
var skill = this.getField(skillName);
|
||||
attributeBase: memoize(preventLoop(function(charId, attributeName){
|
||||
return attributeBase(charId, attributeName);
|
||||
})),
|
||||
skillMod: memoize(preventLoop(function(charId, skillName){
|
||||
var skill = Characters.calculate.getField(charId, skillName);
|
||||
//get the final value of the ability score
|
||||
var ability = this.attributeValue(skill.ability);
|
||||
var ability = Characters.calculate.attributeValue(charId, skill.ability);
|
||||
|
||||
//base modifier
|
||||
var mod = +getMod(ability);
|
||||
|
||||
//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
|
||||
mod += prof * this.attributeValue("proficiencyBonus");
|
||||
mod += prof * Characters.calculate.attributeValue(charId, "proficiencyBonus");
|
||||
|
||||
//apply all effects
|
||||
var rawEffects = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true}
|
||||
).fetch();
|
||||
var effects = _.groupBy(rawEffects, "operation");
|
||||
_.forEach(effects.add, function(effect){
|
||||
mod += evaluateEffect(charId, effect);
|
||||
});
|
||||
_.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);
|
||||
}),
|
||||
var value;
|
||||
var add = 0;
|
||||
var mul = 1;
|
||||
var min = Math.NEGATIVE_INFINITY;
|
||||
var max = Math.POSITIVE_INFINITY;
|
||||
|
||||
proficiency: function(skillName){
|
||||
var charId = this._id;
|
||||
//return largest value in proficiency array
|
||||
var prof = 0;
|
||||
Proficiencies.find(
|
||||
{charId: charId, name: skillName, enabled: true}
|
||||
).forEach(function(proficiency){
|
||||
var newProf = proficiency.value;
|
||||
if (newProf > prof){
|
||||
prof = newProf;
|
||||
Effects.find({
|
||||
charId: charId,
|
||||
stat: skillName,
|
||||
enabled: true,
|
||||
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||
}).forEach(function(effect) {
|
||||
value = evaluateEffect(charId, effect);
|
||||
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;
|
||||
}
|
||||
});
|
||||
return prof;
|
||||
},
|
||||
var result = (mod + add) * mul;
|
||||
if (result < min) result = min;
|
||||
if (result > max) result = max;
|
||||
|
||||
passiveSkill: function(skillName){
|
||||
if (_.isString(skillName)){
|
||||
var skill = this.getField(skillName);
|
||||
}
|
||||
var charId = this._id;
|
||||
var mod = +this.skillMod(skillName);
|
||||
return result;
|
||||
})),
|
||||
proficiency: memoize(function(charId, skillName){
|
||||
//return largest value in proficiency array
|
||||
var prof = Proficiencies.findOne(
|
||||
{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;
|
||||
Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"}
|
||||
).forEach(function(effect){
|
||||
value += evaluateEffect(charId, effect);
|
||||
});
|
||||
var advantage = Characters.calculate.advantage(charId, skillName);
|
||||
value += 5 * advantage;
|
||||
return value;
|
||||
//TODO decide whether (dis)advantage gives (-)+5 to passive checks
|
||||
},
|
||||
|
||||
advantage: function(skillName){
|
||||
var charId = this._id;
|
||||
}),
|
||||
advantage: memoize(function(charId, skillName){
|
||||
var advantage = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "advantage"}
|
||||
).count();
|
||||
@@ -351,19 +402,18 @@ Characters.helpers({
|
||||
if (advantage && !disadvantage) return 1;
|
||||
if (disadvantage && !advantage) return -1;
|
||||
return 0;
|
||||
}),
|
||||
abilityMod: function(charId, attribute){
|
||||
return getMod(
|
||||
Characters.calculate.attributeValue(charId, attribute)
|
||||
);
|
||||
},
|
||||
|
||||
abilityMod: function(attribute){
|
||||
return signedString(getMod(this.attributeValue(attribute)));
|
||||
},
|
||||
|
||||
passiveAbility: function(attribute){
|
||||
var mod = +getMod(this.attributeValue(attribute));
|
||||
passiveAbility: function(charId, attribute){
|
||||
var mod = +getMod(Characters.calculate.attributeValue(charId, attribute));
|
||||
return 10 + mod;
|
||||
},
|
||||
|
||||
xpLevel: function(){
|
||||
var xp = this.experience();
|
||||
xpLevel: function(charId){
|
||||
var xp = Characters.calculate.experience(charId);
|
||||
for (var i = 0; i < 19; i++){
|
||||
if (xp < XP_TABLE[i]){
|
||||
return i;
|
||||
@@ -372,30 +422,103 @@ Characters.helpers({
|
||||
if (xp > 355000) return 20;
|
||||
return 0;
|
||||
},
|
||||
|
||||
level: function(){
|
||||
level: memoize(function(charId){
|
||||
var level = 0;
|
||||
Classes.find({charId: this._id}).forEach(function(cls){
|
||||
Classes.find({charId: charId}).forEach(function(cls){
|
||||
level += cls.level;
|
||||
});
|
||||
return level;
|
||||
},
|
||||
|
||||
experience: function(){
|
||||
}),
|
||||
experience: memoize(function(charId){
|
||||
var xp = 0;
|
||||
Experiences.find(
|
||||
{charId: this._id},
|
||||
{charId: charId},
|
||||
{fields: {value: 1}}
|
||||
).forEach(function(e){
|
||||
xp += e.value;
|
||||
});
|
||||
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
|
||||
Characters.after.remove(function(userId, character) {
|
||||
if (Meteor.isServer){
|
||||
if (Meteor.isServer){
|
||||
Characters.after.remove(function(userId, character) {
|
||||
Actions .remove({charId: character._id});
|
||||
Attacks .remove({charId: character._id});
|
||||
Buffs .remove({charId: character._id});
|
||||
@@ -408,8 +531,8 @@ Characters.after.remove(function(userId, character) {
|
||||
SpellLists .remove({charId: character._id});
|
||||
Items .remove({charId: character._id});
|
||||
Containers .remove({charId: character._id});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Characters.allow({
|
||||
insert: function(userId, doc) {
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
* Damage, healing and resource cost/recovery are all adjustments
|
||||
*/
|
||||
Schemas.Adjustment = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
//which stat the adjustment is applied to
|
||||
stat: {
|
||||
type: String,
|
||||
|
||||
@@ -10,6 +10,7 @@ Schemas.Item = new SimpleSchema({
|
||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
enabled: {type: Boolean, defaultValue: false},
|
||||
requiresAttunement: {type: Boolean, defaultValue: false},
|
||||
"settings.showIncrement": {type: Boolean, defaultValue: false},
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
|
||||
@@ -45,7 +45,26 @@ Meteor.methods({
|
||||
metaData: Object,
|
||||
});
|
||||
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({
|
||||
from: sender,
|
||||
to: "stefan.zermatten@gmail.com",
|
||||
subject: "DiceCloud feedback - " + report.title,
|
||||
text: bodyText,
|
||||
});
|
||||
},
|
||||
deleteReport: function(id) {
|
||||
var user = Meteor.users.findOne(this.userId);
|
||||
|
||||
@@ -4,17 +4,9 @@ Router.configure({
|
||||
});
|
||||
|
||||
Router.plugin("ensureSignedIn", {
|
||||
except: [
|
||||
"home",
|
||||
"atSignIn",
|
||||
"atSignUp",
|
||||
"atForgotPassword",
|
||||
"atResetPwd",
|
||||
"atEnrollAccount",
|
||||
"atVerifyEmail",
|
||||
"atresendVerificationEmail",
|
||||
"loginButtons",
|
||||
"notFound",
|
||||
only: [
|
||||
"profile",
|
||||
"characterList",
|
||||
]
|
||||
});
|
||||
|
||||
@@ -31,7 +23,7 @@ Router.map(function() {
|
||||
this.route("characterList", {
|
||||
path: "/characterList",
|
||||
waitOn: function(){
|
||||
return Meteor.subscribe("characterList", Meteor.userId());
|
||||
return subsManager.subscribe("characterList", Meteor.userId());
|
||||
},
|
||||
data: {
|
||||
characters: function(){
|
||||
@@ -47,7 +39,7 @@ Router.map(function() {
|
||||
path: "/character/:_id",
|
||||
waitOn: function(){
|
||||
return [
|
||||
Meteor.subscribe("singleCharacter", this.params._id, Meteor.userId()),
|
||||
subsManager.subscribe("singleCharacter", this.params._id, Meteor.userId()),
|
||||
];
|
||||
},
|
||||
data: function() {
|
||||
@@ -81,7 +73,7 @@ Router.map(function() {
|
||||
name: "changeLog",
|
||||
waitOn: function() {
|
||||
return [
|
||||
Meteor.subscribe("changeLog"),
|
||||
subsManager.subscribe("changeLog"),
|
||||
]
|
||||
},
|
||||
data: {
|
||||
@@ -93,4 +85,11 @@ Router.map(function() {
|
||||
document.title = appName;
|
||||
},
|
||||
});
|
||||
|
||||
this.route("/guide", {
|
||||
name: "guide",
|
||||
onAfterAction: function() {
|
||||
document.title = appName;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,10 +13,9 @@
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"polymer": "Polymer/polymer#~0.5.4",
|
||||
"core-elements": "Polymer/core-elements#~0.5.4",
|
||||
"paper-elements": "Polymer/paper-elements#~0.5.4",
|
||||
"paper-fab-menu": "cwdoh/paper-fab-menu"
|
||||
"polymer": "Polymer/polymer#~0.5.5",
|
||||
"core-elements": "Polymer/core-elements#~0.5.5",
|
||||
"paper-elements": "Polymer/paper-elements#~0.5.5"
|
||||
},
|
||||
"resolutions": {
|
||||
"core-component-page": "^0.5.0",
|
||||
|
||||
@@ -20,6 +20,11 @@ openParentDialog = function(parent, charId, heroId) {
|
||||
template: "itemDialog",
|
||||
data: {itemId: parent.id},
|
||||
};
|
||||
} else if (parent.collection === "Spells") {
|
||||
detail = {
|
||||
template: "spellDialog",
|
||||
data: {spellId: parent.id},
|
||||
};
|
||||
}
|
||||
detail.heroId = heroId;
|
||||
detail.charId = charId;
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
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 = [];
|
||||
//sp
|
||||
var gp = Math.floor(value);
|
||||
if (gp > 0) {
|
||||
resultArray.push(gp + "gp");
|
||||
}
|
||||
//sp
|
||||
var sp = Math.floor(10 * (value % 1));
|
||||
if (sp > 0) {
|
||||
resultArray.push(sp + "sp");
|
||||
}
|
||||
//cp
|
||||
var cp = 10 * ((value * 10) % 1);
|
||||
cp = Math.round(cp * 1000) / 1000;
|
||||
if (cp > 0) {
|
||||
resultArray.push(cp + "cp");
|
||||
}
|
||||
|
||||
//build string with correct spacing
|
||||
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
|
||||
if (i !== 0) {
|
||||
result += " ";
|
||||
|
||||
96
rpg-docs/client/style/cards.scss
Normal file
96
rpg-docs/client/style/cards.scss
Normal file
@@ -0,0 +1,96 @@
|
||||
@import "bourbon/bourbon";
|
||||
|
||||
$thickColumnWidth: 304px;
|
||||
$thinColumnWidth: 240px;
|
||||
|
||||
//Column layouts of cards
|
||||
.column-container {
|
||||
@include column-fill(balance);
|
||||
@include column-gap(8px);
|
||||
@include column-width($thickColumnWidth);
|
||||
padding: 8px;
|
||||
|
||||
&.thin-columns {
|
||||
@include column-count(4);
|
||||
@include column-width($thinColumnWidth);
|
||||
}
|
||||
}
|
||||
|
||||
//Cards
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: 2px;
|
||||
|
||||
.column-container & {
|
||||
margin-bottom: 8px;
|
||||
width: 100%;
|
||||
//hack to stop flickering
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transform: translateX(0);
|
||||
//stop breaking over column divide
|
||||
-webkit-column-break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
//Fixes extra margin at top of columns
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.top {
|
||||
cursor: pointer;
|
||||
padding: 16px;
|
||||
border-radius: 2px 2px 0 0;
|
||||
&.white {
|
||||
cursor: auto;
|
||||
padding: 16px;
|
||||
border-bottom: rgba(0,0,0,0.12) solid 1px;
|
||||
}
|
||||
paper-checkbox::shadow #ink[checked] {
|
||||
color: #ffffff;
|
||||
}
|
||||
paper-checkbox::shadow #ink {
|
||||
color: #ffffff;
|
||||
}
|
||||
paper-checkbox::shadow #checkbox.checked {
|
||||
background-color: #ffffff;
|
||||
background-color: rgba(255,255,255,0.27);
|
||||
border-color: #ffffff;
|
||||
border-color: rgba(255,255,255,0.27);
|
||||
}
|
||||
paper-checkbox::shadow #checkbox {
|
||||
border-color: #ffffff;
|
||||
border-color: rgba(255,255,255,0.54);
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
padding: 16px;
|
||||
border-radius: 0 0 2px 2px;
|
||||
&.list {
|
||||
padding: 0 0 16px 0;
|
||||
.subhead {
|
||||
color: rgba(0,0,0,0.54);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.010em;
|
||||
padding: 12px 16px 12px 16px;
|
||||
}
|
||||
}
|
||||
&.text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
.left {
|
||||
padding: 16px;
|
||||
border-radius: 2px 0 0 2px;
|
||||
text-align: center;
|
||||
min-width: 72px;
|
||||
}
|
||||
.right {
|
||||
padding: 16px;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* undo pointer cursor on detail box heading */
|
||||
#globalDetail.card .top {
|
||||
cursor: auto;
|
||||
}
|
||||
@@ -70,8 +70,8 @@
|
||||
background-color: #9E9E9E;
|
||||
}
|
||||
|
||||
.blue-grey {
|
||||
background-color: #607D8B;
|
||||
.app-grey {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
.white {
|
||||
37
rpg-docs/client/style/listItem.scss
Normal file
37
rpg-docs/client/style/listItem.scss
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
List items
|
||||
*/
|
||||
.item-slot {
|
||||
background-color: rgb(232, 232, 232);
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.item {
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
height: 40px;
|
||||
margin: 1px 0 1px 0;
|
||||
padding: 0 16px 0 16px;
|
||||
position: relative;
|
||||
transition: box-shadow 0.3s ease, opacity 0.5s ease-in-out;
|
||||
&.small {
|
||||
height: 32px;
|
||||
}
|
||||
&.tall {
|
||||
height: 56px;
|
||||
}
|
||||
&.flexible {
|
||||
height: auto;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
&[hero], &:active{
|
||||
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.37);
|
||||
z-index: 10;
|
||||
}
|
||||
core-icon, paper-icon-button {
|
||||
color: #747474;
|
||||
color: rgba(0,0,0,0.54);
|
||||
}
|
||||
}
|
||||
84
rpg-docs/client/style/main.scss
Normal file
84
rpg-docs/client/style/main.scss
Normal file
@@ -0,0 +1,84 @@
|
||||
@import "bourbon/bourbon";
|
||||
@import "colors";
|
||||
|
||||
//apply a natural box layout model to all elements
|
||||
*, *:before, *:after {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
root {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
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);
|
||||
}
|
||||
|
||||
//Horizontal rule
|
||||
hr {
|
||||
background-color: #444;
|
||||
opacity: 0.12;
|
||||
border-width: 0;
|
||||
color: #444;
|
||||
height: 1px;
|
||||
line-height: 0;
|
||||
margin: 16px -16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
//FABs
|
||||
.floatyButton {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
//Buttons
|
||||
paper-button {
|
||||
color: #000;
|
||||
color: rgba(0,0,0,0.87);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.010;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
//Style shortcuts
|
||||
.scroll-y {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.clickable, core-item, paper-tab {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pre-wrap, .prewrap{
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.padded {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fab-buffer {
|
||||
height: 100px;
|
||||
}
|
||||
20
rpg-docs/client/style/shadowDom.css
Normal file
20
rpg-docs/client/style/shadowDom.css
Normal file
@@ -0,0 +1,20 @@
|
||||
.card .left paper-icon-button {
|
||||
display: block;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.card .left paper-icon-button[disabled] {
|
||||
color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.card .left paper-icon-button /deep/ core-icon {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
/*fix paper-dropdowns*/
|
||||
body /deep/ core-menu {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
24
rpg-docs/client/style/tables.scss
Normal file
24
rpg-docs/client/style/tables.scss
Normal file
@@ -0,0 +1,24 @@
|
||||
td {
|
||||
padding: 8px;
|
||||
&:nth-child(1) {
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.strengthTable{
|
||||
width: 100%;
|
||||
td{
|
||||
&:nth-child(2) {
|
||||
text-align: right;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
width: 250px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.summaryTable {
|
||||
&:nth-child(3){
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
root {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body.core-narrow {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
body /deep/ core-menu {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.calculatedValue {
|
||||
color: #021C33;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.summaryTable td{
|
||||
text-align: right;
|
||||
padding: 4px;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.summaryTable td:first-child {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
hr {
|
||||
background-color: #444;
|
||||
opacity: 0.12;
|
||||
border-width: 0;
|
||||
color: #444;
|
||||
height: 1px;
|
||||
line-height: 0;
|
||||
margin: 0 -16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
paper-button {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
text-transform: uppercase;
|
||||
color: #000;
|
||||
color: rgba(0,0,0,0.87);
|
||||
letter-spacing: 0.010;
|
||||
}
|
||||
|
||||
core-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.listRow {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 8px;
|
||||
/*hack to stop flickering*/
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transform: translateX(0);
|
||||
/*stop divs breaking over divide*/
|
||||
-webkit-column-break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
/*Fixes extra margin at top of columns*/
|
||||
display: inline-block;
|
||||
|
||||
width: 100%;
|
||||
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.card.double {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.card paper-button {
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.cardHeader {
|
||||
height: 48px;
|
||||
padding: 0 16px 0 16px;
|
||||
align-content: center;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
}
|
||||
|
||||
.clickable, .statCard, .abilityMiniCard {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.skillRow {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.resourceCards {
|
||||
padding: 4px 4px 0 4px;
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
|
||||
.resourceCards .card {
|
||||
width: 180px;
|
||||
margin: 4px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
.grey-background, body {
|
||||
background-color: #E0E0E0;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.screen-center {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.scroll-y {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.fab-buffer {
|
||||
height: 88px;
|
||||
width: 100%;
|
||||
order: 999;
|
||||
}
|
||||
|
||||
*[hidden] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.hidden{
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
html /deep/ paper-action-dialog[global-dialog] {
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.floatyButton {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
.wideTable td {
|
||||
padding: 4px 8px 4px 8px;
|
||||
}
|
||||
|
||||
.wideTable table {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
paper-fab-menu /deep/ .container {
|
||||
padding: 24px !important;
|
||||
}
|
||||
|
||||
paper-slider {
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
.list-subhead {
|
||||
color: rgba(0,0,0,0.54);
|
||||
font-size: 14px;
|
||||
height: 40px;
|
||||
padding-left: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.whiteTop {
|
||||
cursor: initial;
|
||||
border-bottom: black solid 0.5px;
|
||||
border-bottom: rgba(0,0,0,0.12) solid 1px;
|
||||
background: white;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
|
||||
.whiteTop paper-icon-button {
|
||||
margin: -8px;
|
||||
}
|
||||
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.padded {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.listPadded {
|
||||
padding: 0 0 16px 0;
|
||||
}
|
||||
|
||||
.rightPadded {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.bottomPadded {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.sideMargin {
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.vertMargin {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.spaceAfter {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.s {
|
||||
padding: 0 0 16px 0;
|
||||
}
|
||||
|
||||
.leftRound{
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
.preline {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.prewrap{
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.white-text .display1{
|
||||
.white-text .display1, .white-text.display1{
|
||||
color: rgba(255,255,255,0.54);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,21 +15,11 @@
|
||||
value={{details}}></paper-input>
|
||||
</div>
|
||||
<div layout horizontal>
|
||||
<!--DamageType-->
|
||||
<paper-dropdown-menu id="damageDiceDropdown" label="Damage Dice">
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu" selected={{damageDice}}>
|
||||
{{#each DAMAGE_DICE}}
|
||||
<paper-item name={{this}} class="containerMenuItem">{{this}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
<!--damageBonus-->
|
||||
<paper-input id="damageInput"
|
||||
label="Damage Bonus"
|
||||
label="Damage"
|
||||
floatinglabel
|
||||
value={{damageBonus}}
|
||||
value={{damage}}
|
||||
flex></paper-input>
|
||||
<!--DamageType-->
|
||||
<paper-dropdown-menu id="damageTypeDropdown" label="Damage Type">
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
var damageTypes = ["bludgeoning", "piercing", "slashing",
|
||||
"acid", "cold", "fire", "force", "lightning", "necrotic",
|
||||
"poison", "psychic", "radiant", "thunder"];
|
||||
var damageTypes = [
|
||||
"bludgeoning",
|
||||
"piercing",
|
||||
"slashing",
|
||||
"acid",
|
||||
"cold",
|
||||
"fire",
|
||||
"force",
|
||||
"lightning",
|
||||
"necrotic",
|
||||
"poison",
|
||||
"psychic",
|
||||
"radiant",
|
||||
"thunder",
|
||||
];
|
||||
|
||||
Template.attackEdit.events({
|
||||
"tap #deleteAttack": function(event, instance) {
|
||||
@@ -13,7 +25,7 @@ Template.attackEdit.events({
|
||||
},
|
||||
"change #damageInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
Attacks.update(this._id, {$set: {damageBonus: value}});
|
||||
Attacks.update(this._id, {$set: {damage: value}});
|
||||
},
|
||||
"change #detailInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
@@ -26,13 +38,6 @@ Template.attackEdit.events({
|
||||
if (value == this.damageType) return;
|
||||
Attacks.update(this._id, {$set: {damageType: value}});
|
||||
},
|
||||
"core-select #damageDiceDropdown": function(event) {
|
||||
var detail = event.originalEvent.detail;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
if (value == this.damageDice) return;
|
||||
Attacks.update(this._id, {$set: {damageDice: value}});
|
||||
}
|
||||
});
|
||||
|
||||
Template.attackEdit.helpers({
|
||||
@@ -41,5 +46,5 @@ Template.attackEdit.helpers({
|
||||
},
|
||||
DAMAGE_DICE: function() {
|
||||
return DAMAGE_DICE;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template name="attackView">
|
||||
<div class="attackView" layout horizontal>
|
||||
<div class="headline rightPadded" layout horizontal center>
|
||||
<div class="headline" style="margin-right: 16px;" layout horizontal center>
|
||||
{{evaluateSigned charId attackBonus}}
|
||||
</div>
|
||||
<div layout vertical>
|
||||
<div>
|
||||
{{damageDice}} {{{evaluateSignedSpaced charId damageBonus}}} {{damageType}}
|
||||
{{evaluateString charId damage}} {{damageType}}
|
||||
</div>
|
||||
{{#if details}}
|
||||
<div class="caption">
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<template name="buffDialog">
|
||||
{{#with buff}}
|
||||
{{#baseDialog title=name class=colorClass hideEdit=true}}
|
||||
{{> buffDetails}}
|
||||
{{/baseDialog}}
|
||||
{{/with}}
|
||||
</template>
|
||||
|
||||
<template name="buffDetails">
|
||||
{{#if description}}
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
{{/if}}
|
||||
|
||||
{{> effectsViewList charId=charId parentId=_id}}
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
Template.buffDialog.helpers({
|
||||
buff: function(){
|
||||
return Buffs.findOne(this.buffId);
|
||||
},
|
||||
});
|
||||
@@ -1,3 +1,27 @@
|
||||
<template name="characterSettings">
|
||||
|
||||
{{#with character}}
|
||||
<div style="height: 100px;">
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td>Hide Spells tab</td>
|
||||
<td>
|
||||
<paper-toggle-button id="hideSpellcasting"
|
||||
checked={{settings.hideSpellcasting}}
|
||||
touch-action="pan-y">
|
||||
</paper-toggle-button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Use variant encumbrance</td>
|
||||
<td>
|
||||
<paper-toggle-button id="variantEncumbrance"
|
||||
checked={{settings.useVariantEncumbrance}}
|
||||
touch-action="pan-y">
|
||||
</paper-toggle-button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{{/with}}
|
||||
<paper-button id="doneButton" affirmative> Done </paper-button>
|
||||
</template>
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
Template.characterSettings.events({
|
||||
|
||||
Template.characterSettings.helpers({
|
||||
character: function() {
|
||||
return Characters.findOne(this._id, {fields: {settings: 1}});
|
||||
}
|
||||
});
|
||||
|
||||
Template.characterSettings.events({
|
||||
"change #variantEncumbrance": function(event, instance){
|
||||
var value = instance.find("#variantEncumbrance").checked;
|
||||
if (this.settings.useVariantEncumbrance !== value){
|
||||
Characters.update(
|
||||
this._id,
|
||||
{$set: {"settings.useVariantEncumbrance": value}}
|
||||
);
|
||||
}
|
||||
},
|
||||
"change #hideSpellcasting": function(event, instance){
|
||||
var value = instance.find("#hideSpellcasting").checked;
|
||||
if (this.settings.hideSpellcasting !== value){
|
||||
Characters.update(
|
||||
this._id,
|
||||
{$set: {"settings.hideSpellcasting": value}}
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
<template name="shareDialog">
|
||||
<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>
|
||||
{{#if readers.count}}
|
||||
<div style="font-weight: 500;">
|
||||
@@ -7,7 +19,7 @@
|
||||
</div>
|
||||
{{#each readers}}
|
||||
<div layout horizontal center>
|
||||
<div flex>{{username}}</div>
|
||||
<div flex>{{getUserName}}</div>
|
||||
<paper-icon-button class="deleteShare" icon="delete"></paper-icon-button>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
@@ -3,6 +3,10 @@ Template.shareDialog.onCreated(function(){
|
||||
});
|
||||
|
||||
Template.shareDialog.helpers({
|
||||
viewPermission: function() {
|
||||
var char = Characters.findOne(this._id, {fields: {settings: 1}});
|
||||
return char.settings.viewPermission || "whitelist";
|
||||
},
|
||||
readers: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {readers: 1}});
|
||||
return Meteor.users.find({_id: {$in: char.readers}});
|
||||
@@ -19,9 +23,20 @@ Template.shareDialog.helpers({
|
||||
return "User not found";
|
||||
}
|
||||
},
|
||||
getUserName: function() {
|
||||
return this.username || "user: " + this._id;
|
||||
}
|
||||
});
|
||||
|
||||
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":
|
||||
function(event, instance){
|
||||
var userName = instance.find("#userNameOrEmailInput").value;
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<paper-item id="shareCharacter">
|
||||
<core-icon icon="social:share"></core-icon>Share
|
||||
</paper-item>
|
||||
<paper-item id="characterSettings">
|
||||
<core-icon icon="settings"></core-icon>Settings
|
||||
</paper-item>
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-menu-button>
|
||||
@@ -28,7 +31,9 @@
|
||||
<paper-tab name="stats">Stats</paper-tab>
|
||||
<paper-tab name="features">Features</paper-tab>
|
||||
<paper-tab name="inventory">Inventory</paper-tab>
|
||||
{{#unless hideSpellcasting}}
|
||||
<paper-tab name="spells">Spells</paper-tab>
|
||||
{{/unless}}
|
||||
<paper-tab name="persona">Persona</paper-tab>
|
||||
<paper-tab name="journal">Journal</paper-tab>
|
||||
</paper-tabs>
|
||||
@@ -39,7 +44,9 @@
|
||||
<section flex name="stats">{{> stats}}</section>
|
||||
<section flex name="features">{{> features}}</section>
|
||||
<section flex name="inventory">{{> inventory}}</section>
|
||||
{{#unless hideSpellcasting}}
|
||||
<section flex name="spells">{{> spells}}</section>
|
||||
{{/unless}}
|
||||
<section flex name="persona">{{> persona}}</section>
|
||||
<section flex name="journal">{{> journal}}</section>
|
||||
</core-animated-pages>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
Template.characterSheet.created = function(){
|
||||
Template.characterSheet.onCreated(function() {
|
||||
//default to the first tab
|
||||
Session.setDefault(this.data._id + ".selectedTab", "stats");
|
||||
};
|
||||
//watch this character and make sure their encumbrance is updated
|
||||
trackEncumbranceConditions(this.data._id, this);
|
||||
});
|
||||
|
||||
var setTab = function(charId, tab){
|
||||
return Session.set(charId + ".selectedTab", tab);
|
||||
@@ -14,6 +17,10 @@ Template.characterSheet.helpers({
|
||||
selectedTab: function(){
|
||||
return getTab(this._id);
|
||||
},
|
||||
hideSpellcasting: function() {
|
||||
var char = Characters.findOne(this._id);
|
||||
return char && char.settings.hideSpellcasting;
|
||||
},
|
||||
});
|
||||
|
||||
Template.characterSheet.events({
|
||||
@@ -40,4 +47,11 @@ Template.characterSheet.events({
|
||||
template: "shareDialog",
|
||||
});
|
||||
},
|
||||
"tap #characterSettings": function(event, instance){
|
||||
GlobalUI.showDialog({
|
||||
heading: this.name + " Settings",
|
||||
data: this,
|
||||
template: "characterSettings",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
body /deep/ #statGroupDropDown {
|
||||
width: 120px;
|
||||
html /deep/ .operationDropDown {
|
||||
width: 152px;
|
||||
}
|
||||
|
||||
body /deep/ #statDropDown {
|
||||
width: 120px;
|
||||
html /deep/ .statDropDown {
|
||||
width: 152px;
|
||||
}
|
||||
|
||||
body /deep/ #operationDropDown {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
body /deep/ #damageMultiplierDropDown {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
body /deep/ #proficiencyDropDown {
|
||||
width: 120px;
|
||||
html /deep/ .damageMultiplierDropDown {
|
||||
width: 152px;
|
||||
}
|
||||
|
||||
html /deep/ .effectEdit paper-input {
|
||||
@@ -24,6 +16,7 @@ html /deep/ .effectEdit paper-input {
|
||||
}
|
||||
|
||||
html /deep/ .effectEdit {
|
||||
height: 64px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,23 @@
|
||||
<template name="effectEdit">
|
||||
<div class="effectEdit" layout horizontal center>
|
||||
<paper-dropdown-menu class="statGroupDropDown" label="Stat Group" flex>
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu statGroupMenu" selected={{selectedStatGroup}}>
|
||||
{{#each statGroups}}
|
||||
<paper-item class="statGroupSelect" name={{this}}>{{this}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{#if stats}}
|
||||
<paper-dropdown-menu class="statDropDown" label="Stat" flex>
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu statMenu" selected={{stat}} on-tap="onStatMenuTap">
|
||||
{{#each stats}}
|
||||
<paper-item name={{stat}}>{{name}}</paper-item>
|
||||
<paper-dropdown-menu class="statDropDown"
|
||||
label="Stat">
|
||||
<paper-dropdown layered
|
||||
class="dropdown">
|
||||
<core-menu class="menu statMenu" selected={{stat}}>
|
||||
{{#each statGroups}}
|
||||
<div style="font-weight: bold;
|
||||
margin-top: 16px;">{{this}}</div>
|
||||
{{#each stats}}
|
||||
<paper-item name={{stat}}>{{name}}</paper-item>
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{#if operations}}
|
||||
<paper-dropdown-menu class="operationDropDown" label="Operation" flex>
|
||||
<paper-dropdown-menu class="operationDropDown"
|
||||
label="Operation">
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu operationMenu" selected={{operation}}>
|
||||
{{#each operations}}
|
||||
@@ -31,24 +27,39 @@
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
{{> Template.dynamic template=effectValueTemplate}}
|
||||
<paper-icon-button class="deleteEffect" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
||||
{{#if effectValueTemplate}}
|
||||
{{> Template.dynamic template=effectValueTemplate}}
|
||||
{{else}}
|
||||
<div flex></div>
|
||||
{{/if}}
|
||||
<paper-icon-button class="deleteEffect"
|
||||
icon="delete">
|
||||
</paper-icon-button>
|
||||
<br>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="regularEffectValue">
|
||||
<paper-input class="effectValueInput" label="Value" floatinglabel value={{effectValue}} flex></paper-input>
|
||||
<paper-input class="effectValueInput"
|
||||
label="Value"
|
||||
floatinglabel
|
||||
value={{effectValue}}
|
||||
flex>
|
||||
</paper-input>
|
||||
</template>
|
||||
|
||||
<template name="multiplierEffectValue">
|
||||
<paper-dropdown-menu class="damageMultiplierDropDown" label="Damage Multiplier" flex>
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu multiplierMenu" selected={{value}}>
|
||||
<paper-dropdown-menu class="damageMultiplierDropDown"
|
||||
label="Damage Multiplier">
|
||||
<paper-dropdown layered
|
||||
class="dropdown">
|
||||
<core-menu class="menu multiplierMenu"
|
||||
selected={{value}}>
|
||||
<paper-item name="0.5">Resistance</paper-item>
|
||||
<paper-item name="2">Vulnerability</paper-item>
|
||||
<paper-item name="0">Immunity</paper-item>
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
<div flex></div>
|
||||
</template>
|
||||
|
||||
@@ -93,24 +93,17 @@ var skillOperations = [
|
||||
{name: "Conditional Benefit", operation: "conditional"}
|
||||
];
|
||||
|
||||
Template.effectEdit.created = function(){
|
||||
var statGroup = statsDict[this.data.stat] && statsDict[this.data.stat].group;
|
||||
this.selectedStatGroup = new ReactiveVar(statGroup);
|
||||
};
|
||||
|
||||
Template.effectEdit.helpers({
|
||||
selectedStatGroup: function(){
|
||||
return Template.instance().selectedStatGroup.get();
|
||||
},
|
||||
statGroups: function(){
|
||||
return statGroupNames;
|
||||
},
|
||||
stats: function(){
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
var group = this;
|
||||
return statGroups[group];
|
||||
},
|
||||
operations: function(){
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
var stat = statsDict[this.stat];
|
||||
var group = stat && stat.group;
|
||||
if (group === "Weakness/Resistance") return null;
|
||||
if (group === "Saving Throws" || group === "Skills"){
|
||||
return skillOperations;
|
||||
@@ -120,7 +113,8 @@ Template.effectEdit.helpers({
|
||||
},
|
||||
effectValueTemplate: function(){
|
||||
//resistance/vulnerability template
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
var stat = statsDict[this.stat];
|
||||
var group = stat && stat.group;
|
||||
if (group === "Weakness/Resistance") return "multiplierEffectValue";
|
||||
|
||||
var op = this.operation;
|
||||
@@ -144,25 +138,6 @@ Template.effectEdit.events({
|
||||
Effects.softRemoveNode(this._id);
|
||||
GlobalUI.deletedToast(this._id, "Effects", "Effect");
|
||||
},
|
||||
"core-select .statGroupDropDown": function(event, instance){
|
||||
var detail = event.originalEvent.detail;
|
||||
if (!detail.isSelected) return;
|
||||
var groupName = detail.item.getAttribute("name");
|
||||
var oldName = Template.instance().selectedStatGroup.get();
|
||||
if (oldName != groupName){
|
||||
instance.selectedStatGroup.set(groupName);
|
||||
if (groupName === "Weakness/Resistance"){
|
||||
Effects.update(this._id, {$set: {
|
||||
value: 0.5,
|
||||
calculation: "",
|
||||
operation: "mul"}, $unset: {stat: ""}});
|
||||
} else {
|
||||
Effects.update(this._id,
|
||||
{$set: {operation: "add"},
|
||||
$unset: {stat: "", value: "", calculation: ""}});
|
||||
}
|
||||
}
|
||||
},
|
||||
"core-select .statDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if (!detail.isSelected) return;
|
||||
|
||||
@@ -57,40 +57,40 @@ var stats = {
|
||||
"d12HitDice":{"name":"d12 Hit Dice"},
|
||||
"acidMultiplier":{"name":"Acid damage", "group": "Weakness/Resistance"},
|
||||
"bludgeoningMultiplier":{
|
||||
"name":"Bludgeoning damage", "group": "Weakness/Resistance"
|
||||
"name":"Bludgeoning damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"coldMultiplier":{
|
||||
"name":"Cold damage", "group": "Weakness/Resistance"
|
||||
"name":"Cold damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"fireMultiplier":{
|
||||
"name":"Fire damage", "group": "Weakness/Resistance"
|
||||
"name":"Fire damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"forceMultiplier":{
|
||||
"name":"Force damage", "group": "Weakness/Resistance"
|
||||
"name":"Force damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"lightningMultiplier":{
|
||||
"name":"Lightning damage", "group": "Weakness/Resistance"
|
||||
"name":"Lightning damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"necroticMultiplier":{
|
||||
"name":"Necrotic damage", "group": "Weakness/Resistance"
|
||||
"name":"Necrotic damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"piercingMultiplier":{
|
||||
"name":"Piercing damage", "group": "Weakness/Resistance"
|
||||
"name":"Piercing damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"poisonMultiplier":{
|
||||
"name":"Poison damage", "group": "Weakness/Resistance"
|
||||
"name":"Poison damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"psychicMultiplier":{
|
||||
"name":"Psychic damage", "group": "Weakness/Resistance"
|
||||
"name":"Psychic damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"radiantMultiplier":{
|
||||
"name":"Radiant damage", "group": "Weakness/Resistance"
|
||||
"name":"Radiant damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"slashingMultiplier":{
|
||||
"name":"Slashing damage", "group": "Weakness/Resistance"
|
||||
"name":"Slashing damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"thunderMultiplier":{
|
||||
"name":"Thunder damage", "group": "Weakness/Resistance"
|
||||
"name":"Thunder damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -110,8 +110,8 @@ var operations = {
|
||||
Template.effectView.helpers({
|
||||
sourceName: function(){
|
||||
var id = this.parent.id;
|
||||
if(!id) return;
|
||||
switch(this.parent.collection){
|
||||
if (!id) return;
|
||||
switch (this.parent.collection){
|
||||
case "Features":
|
||||
return "Feature - " + Features.findOne(id, {fields: {name: 1}}).name;
|
||||
case "Classes":
|
||||
@@ -130,33 +130,39 @@ Template.effectView.helpers({
|
||||
return stats[this.stat] && stats[this.stat].name || "No Stat";
|
||||
},
|
||||
operationName: function(){
|
||||
if(this.operation === "proficiency" ||
|
||||
if (this.operation === "proficiency" ||
|
||||
this.operation === "conditional") return null;
|
||||
if(stats[this.stat].group === "Weakness/Resistance") return null;
|
||||
if(this.operation === "add" && evaluateEffect(this.charId, this) < 0) return null;
|
||||
return operations[this.operation] && operations[this.operation].name || "No Operation";
|
||||
if (stats[this.stat] && stats[this.stat].group === "Weakness/Resistance")
|
||||
return null;
|
||||
if (this.operation === "add" && evaluateEffect(this.charId, this) < 0)
|
||||
return null;
|
||||
return operations[this.operation] &&
|
||||
operations[this.operation].name || "No Operation";
|
||||
},
|
||||
statValue: function(){
|
||||
if(this.operation === "advantage" ||
|
||||
if (this.operation === "advantage" ||
|
||||
this.operation === "disadvantage" ||
|
||||
this.operation === "fail"){
|
||||
return null;
|
||||
}
|
||||
if(this.operation === "proficiency"){
|
||||
if(this.value == 0.5 || this.calculation == 0.5) return "Half Proficiency";
|
||||
if(this.value == 1 || this.calculation == 1) return "Proficiency";
|
||||
if(this.value == 2 || this.calculation == 2) return "Double Proficiency";
|
||||
if (this.operation === "proficiency"){
|
||||
if (this.value == 0.5 || this.calculation == 0.5)
|
||||
return "Half Proficiency";
|
||||
if (this.value == 1 || this.calculation == 1)
|
||||
return "Proficiency";
|
||||
if (this.value == 2 || this.calculation == 2)
|
||||
return "Double Proficiency";
|
||||
}
|
||||
if(this.operation === "conditional"){
|
||||
if (this.operation === "conditional"){
|
||||
return this.calculation || this.value;
|
||||
}
|
||||
if(stats[this.stat].group === "Weakness/Resistance"){
|
||||
if(this.value === 0.5) return "Resistance";
|
||||
if(this.value === 2) return "Vulnerability";
|
||||
if(this.value === 0) return "Immunity";
|
||||
if (stats[this.stat] && stats[this.stat].group === "Weakness/Resistance"){
|
||||
if (this.value === 0.5) return "Resistance";
|
||||
if (this.value === 2) return "Vulnerability";
|
||||
if (this.value === 0) return "Immunity";
|
||||
}
|
||||
var value = evaluateEffect(this.charId, this);
|
||||
if(_.isNumber(value)) return value;
|
||||
if (_.isNumber(value)) return value;
|
||||
return this.calculation || this.value;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if description}}
|
||||
<div class="prewrap">{{description}}</div>
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
{{/if}}
|
||||
|
||||
{{> effectsViewList charId=charId parentId=_id}}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template name="features">
|
||||
<div fit>
|
||||
<div class="scroll-y" fit>
|
||||
<div class="containers">
|
||||
<div class="column-container">
|
||||
<!--expertiseDice-->
|
||||
{{>resource name="expertiseDice" title="Expertise Dice" color="teal" char=this}}
|
||||
<!--ki-->
|
||||
@@ -14,27 +14,27 @@
|
||||
{{>resource name="superiorityDice" title="Superiority Dice" color="teal" char=this}}
|
||||
|
||||
<!--Attacks-->
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
|
||||
<div class="whiteTop" hero-id="toolbar" layout horizontal center {{detailHero}}>
|
||||
<div flex>
|
||||
<div class="containerName subhead">Attacks</div>
|
||||
</div>
|
||||
<!--<paper-icon-button class="black54" id="addAttackButton" icon="add"></paper-icon-button>-->
|
||||
<paper-shadow class="card">
|
||||
<div class="top white">
|
||||
Attacks
|
||||
</div>
|
||||
<div class="containerMain listPadded">
|
||||
<div class="bottom list">
|
||||
{{#each attacks}}
|
||||
<div class="itemSlot">
|
||||
<paper-item class="white attack" hero-id="main" {{detailHero}}>
|
||||
<div layout horizontal class="fullwidth">
|
||||
<div class="headline rightPadded" layout horizontal center>
|
||||
<div class="item-slot">
|
||||
<div class="flexible attack item"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div layout horizontal>
|
||||
<div class="headline"
|
||||
style="margin-right: 16px;"
|
||||
layout horizontal center>
|
||||
{{evaluateSigned ../_id attackBonus}}
|
||||
</div>
|
||||
<div layout vertical flex>
|
||||
<div flex layout vertical>
|
||||
<div class="body2">
|
||||
{{name}}
|
||||
</div>
|
||||
<div>
|
||||
{{damageDice}} {{{evaluateSignedSpaced ../_id damageBonus}}} {{damageType}}
|
||||
{{evaluateString ../_id damage}} {{damageType}}
|
||||
</div>
|
||||
{{#if details}}
|
||||
<div class="caption">
|
||||
@@ -43,34 +43,32 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</paper-item>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
|
||||
<!--Proficiencies-->
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero "proficiencies"}}>
|
||||
<div id="proficiencies"
|
||||
class="whiteTop"
|
||||
layout horizontal center>
|
||||
<div class="containerName subhead">Proficiencies</div>
|
||||
<paper-shadow class="card">
|
||||
<div class="white top">
|
||||
Proficiencies
|
||||
</div>
|
||||
<div flex class="containerMain listPadded">
|
||||
<div flex class="bottom list">
|
||||
{{#if weaponProfs.count}}
|
||||
<div class="list-subhead" layout horizontal center>Weapons</div>
|
||||
<div class="subhead">Weapons</div>
|
||||
{{/if}}
|
||||
{{#each weaponProfs}}
|
||||
{{> proficiencyListItem}}
|
||||
{{/each}}
|
||||
{{#if armorProfs.count}}
|
||||
<div class="list-subhead" layout horizontal center>Armor</div>
|
||||
<div class="subhead">Armor</div>
|
||||
{{/if}}
|
||||
{{#each armorProfs}}
|
||||
{{> proficiencyListItem}}
|
||||
{{/each}}
|
||||
{{#if toolProfs.count}}
|
||||
<div class="list-subhead" layout horizontal center>Tools</div>
|
||||
<div class="subhead">Tools</div>
|
||||
{{/if}}
|
||||
{{#each toolProfs}}
|
||||
{{> proficiencyListItem}}
|
||||
@@ -80,23 +78,42 @@
|
||||
|
||||
<!--features-->
|
||||
{{#each features}}
|
||||
<paper-shadow class="card container featureCard" hero-id="main" {{detailHero}}>
|
||||
<div class="containerTop {{colorClass}}" hero-id="toolbar" layout horizontal center {{detailHero}}>
|
||||
<paper-ripple fit></paper-ripple>
|
||||
<div class="containerName subhead" hero-id="title" flex {{detailHero}}>{{name}}</div>
|
||||
{{#if hasUses}}<div class="subhead" style="margin-right: 8px">{{usesLeft}}/{{usesValue}}</div>{{/if}}
|
||||
<paper-ripple fit></paper-ripple>
|
||||
<paper-shadow class="card featureCard"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="top {{colorClass}} subhead"
|
||||
layout horizontal
|
||||
hero-id="toolbar" {{detailHero}}>
|
||||
<div flex hero-id="title" {{detailHero}}>
|
||||
{{name}}
|
||||
</div>
|
||||
{{#if hasUses}}
|
||||
<div style="margin-right: 8px">
|
||||
{{usesLeft}}/{{usesValue}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if canEnable}}
|
||||
<core-tooltip label="Feature enabled" position="left">
|
||||
<paper-checkbox class="enabledCheckbox" checked={{enabled}}></paper-checkbox>
|
||||
<core-tooltip label="Feature enabled"
|
||||
position="left">
|
||||
<paper-checkbox class="enabledCheckbox"
|
||||
checked={{enabled}}>
|
||||
</paper-checkbox>
|
||||
</core-tooltip>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if description}}<div flex class="containerMain body1 featureDescription">{{description}}</div>{{/if}}
|
||||
{{#if description}}
|
||||
<div flex class="bottom text"
|
||||
>{{evaluateString charId description}}</div>
|
||||
{{/if}}
|
||||
{{#if hasUses}}
|
||||
<div class="containerFoot" layout horizontal center end-justified>
|
||||
<paper-button class="useFeature" disabled={{noUsesLeft}}>Use</paper-button>
|
||||
<paper-button class="resetFeature" disabled={{usesFull}}>Reset</paper-button>
|
||||
<div layout horizontal center end-justified>
|
||||
<paper-button class="useFeature"
|
||||
disabled={{noUsesLeft}}>
|
||||
Use
|
||||
</paper-button>
|
||||
<paper-button class="resetFeature"
|
||||
disabled={{usesFull}}>
|
||||
Reset
|
||||
</paper-button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</paper-shadow>
|
||||
@@ -118,19 +135,29 @@
|
||||
</template>
|
||||
|
||||
<template name="resource">
|
||||
{{#if char.attributeBase name}}
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero name char._id}} layout horizontal>
|
||||
<div class="containerLeft {{getColor}}" hero-id="toolbar" {{detailHero name char._id}} >
|
||||
<div class="resourceButtons">
|
||||
<paper-icon-button class="resourceUp" icon="arrow-drop-up" disabled={{cantIncrement}}></paper-icon-button>
|
||||
<paper-icon-button class="resourceDown" icon="arrow-drop-down" disabled={{cantDecrement}}></paper-icon-button>
|
||||
{{#if characterCalculate "attributeBase" char._id name}}
|
||||
<paper-shadow class="card"
|
||||
hero-id="main" {{detailHero name char._id}}
|
||||
layout horizontal>
|
||||
<div class="left {{getColor}} display1 white-text"
|
||||
hero-id="toolbar" {{detailHero name char._id}}
|
||||
layout horizontal center>
|
||||
<div style="margin-right: 8px;">
|
||||
<paper-icon-button class="resourceUp"
|
||||
icon="arrow-drop-up"
|
||||
disabled={{cantIncrement}}>
|
||||
</paper-icon-button>
|
||||
<paper-icon-button class="resourceDown"
|
||||
icon="arrow-drop-down"
|
||||
disabled={{cantDecrement}}>
|
||||
</paper-icon-button>
|
||||
</div>
|
||||
<div class="resourceValue">{{char.attributeValue name}}</div>
|
||||
<!--<div class="resourceMax">{{char.attributeBase name}}</div>-->
|
||||
<div>{{characterCalculate "attributeValue" char._id name}}</div>
|
||||
<!--<div>/{{char.attributeBase name}}</div>-->
|
||||
</div>
|
||||
<div class="containerRight clickable" flex relative horizontal layout center>
|
||||
<div class="right clickable"
|
||||
flex layout horizontal center>
|
||||
{{title}}
|
||||
<paper-ripple fit></paper-ripple>
|
||||
</div>
|
||||
</paper-shadow>
|
||||
{{/if}}
|
||||
|
||||
@@ -65,7 +65,7 @@ Template.features.events({
|
||||
}
|
||||
});
|
||||
},
|
||||
"tap .featureCard .containerTop": function(event){
|
||||
"tap .featureCard .top": function(event){
|
||||
var featureId = this._id;
|
||||
var charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
@@ -96,12 +96,14 @@ Template.features.events({
|
||||
|
||||
Template.resource.helpers({
|
||||
cantIncrement: function(){
|
||||
var baseBigger = 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);
|
||||
var baseBigger = value < base;
|
||||
return !baseBigger;
|
||||
},
|
||||
cantDecrement: function(){
|
||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
var valuePositive = value > 0;
|
||||
return !valuePositive;
|
||||
},
|
||||
getColor: function(){
|
||||
@@ -115,20 +117,23 @@ Template.resource.helpers({
|
||||
|
||||
Template.resource.events({
|
||||
"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: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .resourceDown": function(event){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
if (value > 0){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .containerRight": function(event, instance) {
|
||||
"tap .right": function(event, instance) {
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: this.title, statName: this.name, charId: this.char._id},
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<template name="carryCapacityBar">
|
||||
<div class="carryCapacityBar">
|
||||
<div class="carriedWeightBar"
|
||||
style="width: {{carriedPercent}}%;
|
||||
background-color: {{carriedColor}}">
|
||||
</div>
|
||||
<div class="tick"
|
||||
style="width: 33.333%;">
|
||||
</div>
|
||||
<div class="tick"
|
||||
style="width: 66.666%;">
|
||||
</div>
|
||||
</div>
|
||||
{{#if overCarriedPercent}}
|
||||
<div class="carryCapacityBar">
|
||||
<div class="carriedWeightBar"
|
||||
style="width: {{overCarriedPercent}}%;
|
||||
background-color: {{overCarriedColor}}">
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
@@ -0,0 +1,65 @@
|
||||
var getFractionCarried = function(char) {
|
||||
//find out the weight
|
||||
var weight = 0;
|
||||
Containers.find(
|
||||
{charId: char._id, isCarried: true}
|
||||
).forEach(function(container){
|
||||
weight += container.totalWeight();
|
||||
});
|
||||
Items.find(
|
||||
{charId: char._id, "parent.id": char._id},
|
||||
{fields: {weight : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
weight += item.totalWeight();
|
||||
});
|
||||
//get strength
|
||||
var strength = Characters.calculate.attributeValue(char._id, "strength");
|
||||
var capacity = strength * 15;
|
||||
return weight / capacity;
|
||||
};
|
||||
|
||||
Template.carryCapacityBar.onCreated(function() {
|
||||
var self = this;
|
||||
self.carriedFraction = new ReactiveVar(0);
|
||||
self.autorun(function() {
|
||||
self.carriedFraction.set(getFractionCarried(self.data));
|
||||
});
|
||||
});
|
||||
|
||||
Template.carryCapacityBar.helpers({
|
||||
carriedPercent: function() {
|
||||
var percent = 100 * Template.instance().carriedFraction.get();
|
||||
return percent > 100 ? 100 : percent;
|
||||
},
|
||||
overCarriedPercent: function() {
|
||||
var percent = 100 * Template.instance().carriedFraction.get();
|
||||
var overPercent = percent - 100;
|
||||
if (overPercent < 0) return 0;
|
||||
if (overPercent > 100) return 100;
|
||||
return overPercent;
|
||||
},
|
||||
carriedColor: function() {
|
||||
var frac = Template.instance().carriedFraction.get();
|
||||
if (frac < 1 / 3){
|
||||
return "#2196F3";
|
||||
} else if (frac < 2 / 3){
|
||||
return "#CDDC39";
|
||||
} else if (frac < 1) {
|
||||
return "#FFC107";
|
||||
} else {
|
||||
return "#F44336";
|
||||
}
|
||||
},
|
||||
overCarriedColor: function() {
|
||||
var frac = Template.instance().carriedFraction.get();
|
||||
if (frac < 1 / 3){
|
||||
return "#2196F3";
|
||||
} else if (frac < 2 / 3){
|
||||
return "#CDDC39";
|
||||
} else if (frac < 1) {
|
||||
return "#FFC107";
|
||||
} else {
|
||||
return "#F44336";
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
.carryCapacityBar {
|
||||
background-color: #7DC580;
|
||||
background-color: rgba(255,255,255,0.27);
|
||||
position: relative;
|
||||
height: 4px;
|
||||
div{
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
.tick {
|
||||
border-right: solid 2px #E5E5E5;
|
||||
border-right-color: rgba(255,255,255,0.54);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<template name="carryDialog">
|
||||
{{#baseDialog title="Weight Carried" class=color hideEdit=true}}
|
||||
<div layout horizontal center-justified end>
|
||||
<div class="display2">
|
||||
{{round carriedWeight 1}}
|
||||
</div>
|
||||
<div class="display1">
|
||||
lbs
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="vertMargin">
|
||||
|
||||
{{> carryCapacityTable}}
|
||||
|
||||
{{/baseDialog}}
|
||||
</template>
|
||||
@@ -0,0 +1,20 @@
|
||||
Template.carryDialog.helpers({
|
||||
carriedWeight: function() {
|
||||
var weight = 0;
|
||||
Containers.find(
|
||||
{charId: this.charId, isCarried: true}
|
||||
).forEach(function(container){
|
||||
weight += container.totalWeight();
|
||||
});
|
||||
Items.find(
|
||||
{charId: this.charId, "parent.id": this.charId},
|
||||
{fields: {weight : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
weight += item.totalWeight();
|
||||
});
|
||||
return weight;
|
||||
},
|
||||
color: function() {
|
||||
if (this.color) return this.color + " white-text";
|
||||
},
|
||||
});
|
||||
@@ -34,13 +34,13 @@
|
||||
<template name="containerView">
|
||||
<div layout horizontal wrap center justified>
|
||||
<table class="summaryTable fullwidth">
|
||||
<tr><td>Container</td><td>{{weight}}lbs</td><td>{{longValueString value}}</td></tr>
|
||||
<tr><td>Contents</td><td>{{contentsWeight}}lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
||||
<tr class="body2"><td>Total</td><td>{{totalWeight}}lbs</td><td>{{longValueString totalValue}}</td></tr>
|
||||
<tr><td>Container</td><td>{{round weight}}lbs</td><td>{{longValueString value}}</td></tr>
|
||||
<tr><td>Contents</td><td>{{round contentsWeight}}lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
||||
<tr class="body2"><td>Total</td><td>{{round totalWeight}}lbs</td><td>{{longValueString totalValue}}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
{{#if description}}
|
||||
<hr class="vertMargin">
|
||||
<div class="prewrap">{{description}}</div>
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
div#stats {
|
||||
-webkit-column-width: 200px;
|
||||
-moz-column-width: 200px;
|
||||
column-width: 200px;
|
||||
-webkit-column-count: 4;
|
||||
-moz-column-count: 4;
|
||||
column-count: 4;
|
||||
}
|
||||
|
||||
.containers {
|
||||
-webkit-column-width: 300px;
|
||||
-moz-column-width: 300px;
|
||||
column-width: 300px;
|
||||
-webkit-column-gap: 8px;
|
||||
-moz-column-gap: 8px;
|
||||
column-gap: 8px;
|
||||
-moz-column-fill: balance;
|
||||
column-fill: balance;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.containerLeft {
|
||||
padding: 16px 16px 16px 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: row;
|
||||
border-radius: 2px 0 0 2px;
|
||||
|
||||
/* same style as display-1 */
|
||||
font-size: 34px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
color: rgba(255,255,255,0.54);
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.statCard .containerLeft {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.containerRight {
|
||||
padding: 16px;
|
||||
|
||||
/* same style as subhead */
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
color: #000;
|
||||
color: rgba(0,0,0,0.87);
|
||||
letter-spacing: 0.010em;
|
||||
}
|
||||
|
||||
.resourceValue {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.resourceMax {
|
||||
display: inline-block;
|
||||
align-self: flex-end;
|
||||
|
||||
/* same style as subhead */
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
color: rgba(255,255,255,0.54);
|
||||
letter-spacing: 0.010em;
|
||||
}
|
||||
|
||||
.resourceMax:before {
|
||||
content: "/";
|
||||
}
|
||||
|
||||
.resourceButtons {
|
||||
margin: -16px 8px -16px -16px;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.resourceButtons paper-icon-button{
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.resourceButtons paper-icon-button[disabled]{
|
||||
color: rgba(255, 255, 255, 0.26);
|
||||
}
|
||||
|
||||
.resourceButtons /deep/ core-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.containerTop {
|
||||
cursor: pointer;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
|
||||
.equipmentTop {
|
||||
padding: 16px;
|
||||
border-bottom: rgba(0,0,0,0.12) solid 1px;
|
||||
}
|
||||
|
||||
.containerMain {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.equipmentMain {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.inventoryItem {
|
||||
background: white;
|
||||
transition: box-shadow 0.3s ease,
|
||||
opacity 0.5s ease-in-out;
|
||||
height: 40px;
|
||||
margin: 1px 0 1px 0;
|
||||
font-size: 16px;
|
||||
color: rgba(0,0,0,0.87);
|
||||
letter-spacing: 0.010em;
|
||||
}
|
||||
|
||||
.inventoryItem core-icon, .inventoryItem paper-icon-button {
|
||||
color: rgba(0,0,0,0.54);
|
||||
}
|
||||
|
||||
.inventoryItem core-icon {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.inventoryItem /deep/ .button-content {
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
-webkit-flex-basis: 0.000000001px;
|
||||
flex-basis: 0.000000001px;
|
||||
}
|
||||
|
||||
.inventoryItem[hero] {
|
||||
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.37);
|
||||
}
|
||||
|
||||
.itemSlot {
|
||||
background-color: rgb(232, 232, 232);
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#inventory .containerMain {
|
||||
padding: 0 0 16px 0;
|
||||
}
|
||||
@@ -1,73 +1,124 @@
|
||||
<template name="inventory">
|
||||
<div fit>
|
||||
<div id="inventory" class="scroll-y" fit>
|
||||
<div class="containers">
|
||||
<div class="column-container">
|
||||
<!--Net Worth-->
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero}} layout horizontal>
|
||||
<div class="indigo white-text subhead padded leftRound" layout horizontal center>
|
||||
Net Worth
|
||||
</div>
|
||||
<div class="padded" layout horizontal center>
|
||||
{{valueString netWorth}}
|
||||
<paper-shadow class="card">
|
||||
<div class="white top" layout horizontal center>
|
||||
<div class="subhead" flex>
|
||||
Net Worth
|
||||
</div>
|
||||
<div>
|
||||
{{valueString netWorth}}
|
||||
</div>
|
||||
</div>
|
||||
</paper-shadow>
|
||||
<!--Weight Carried-->
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero}} layout horizontal>
|
||||
<div class="green white-text subhead padded leftRound" layout horizontal center>
|
||||
Weight Carried
|
||||
<paper-shadow class="card"
|
||||
hero-id="main" {{detailHero "weightCarried" _id}}>
|
||||
<div class="top green white-text weightCarried"
|
||||
hero-id="toolbar" {{detailHero "weightCarried" _id}}
|
||||
layout horizontal center>
|
||||
<div class="subhead" flex>
|
||||
Weight Carried
|
||||
</div>
|
||||
<div>
|
||||
{{round weightCarried}}lbs
|
||||
</div>
|
||||
</div>
|
||||
<div class="padded" layout horizontal center>
|
||||
{{round weightCarried}}lbs
|
||||
<div class="bottom green" style="padding: 0;">
|
||||
{{> carryCapacityBar}}
|
||||
</div>
|
||||
{{#if encumberedBuffs.count}}
|
||||
<div class="bottom list">
|
||||
{{#each encumberedBuffs}}
|
||||
<div class="item-slot">
|
||||
<div class="item buff"
|
||||
hero-id="main" {{detailHero}}
|
||||
layout horizontal center
|
||||
draggable="true">
|
||||
<div flex>
|
||||
<core-icon icon="work"
|
||||
style="margin-right: 16px">
|
||||
</core-icon>
|
||||
{{name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</paper-shadow>
|
||||
<!--Equipment-->
|
||||
<paper-shadow class="card container equipmentContainer">
|
||||
<div class="equipmentTop" layout horizontal center>
|
||||
<div class="containerName subhead" flex>
|
||||
<paper-shadow class="card equipmentContainer">
|
||||
<div class="white top" layout horizontal center>
|
||||
<div class="subhead" flex>
|
||||
Equipment
|
||||
</div>
|
||||
<div class="caption" style="margin-right: 8px">{{valueString equipmentValue}}</div>
|
||||
<div class="caption">{{round equipmentWeight}}lbs</div>
|
||||
<div class="caption" style="margin-right: 8px">
|
||||
{{valueString equipmentValue}}
|
||||
</div>
|
||||
<div class="caption">
|
||||
{{round equipmentWeight}}lbs
|
||||
</div>
|
||||
</div>
|
||||
<div flex class="equipmentMain">
|
||||
<div flex class="bottom list">
|
||||
{{#if attuned.count}}
|
||||
<div class="list-subhead" layout horizontal center>Attuned</div>
|
||||
<div class="subhead">Attuned</div>
|
||||
{{/if}}
|
||||
{{#each attuned}}
|
||||
{{>inventoryItem}}
|
||||
{{/each}}
|
||||
{{#if attuned.count}}<div class="list-subhead" layout horizontal center>Equipment</div>{{/if}}
|
||||
{{#if attuned.count}}
|
||||
<div class="subhead">Equipment</div>
|
||||
{{/if}}
|
||||
{{#each equipment}}
|
||||
{{>inventoryItem}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
<!--Carried Items-->
|
||||
<paper-shadow class="card container carriedContainer">
|
||||
<div class="equipmentTop" layout horizontal center>
|
||||
<div class="containerName subhead" flex>
|
||||
<paper-shadow class="card carriedContainer">
|
||||
<div class="white top" layout horizontal center>
|
||||
<div class="subhead" flex>
|
||||
Carried
|
||||
</div>
|
||||
<div class="caption" style="margin-right: 8px">{{valueString carriedValue}}</div>
|
||||
<div class="caption">{{round carriedWeight}}lbs</div>
|
||||
<div class="caption" style="margin-right: 8px">
|
||||
{{valueString carriedValue}}
|
||||
</div>
|
||||
<div class="caption">
|
||||
{{round carriedWeight}}lbs
|
||||
</div>
|
||||
</div>
|
||||
<div flex class="containerMain">
|
||||
<div flex class="bottom list">
|
||||
{{#each carriedItems}}
|
||||
{{>inventoryItem}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
{{#each containers}}
|
||||
<paper-shadow class="card container itemContainer" hero-id="main" {{detailHero}} style="order: {{containerOrder}};">
|
||||
<div class="containerTop {{colorClass}}" hero-id="toolbar" layout horizontal center {{detailHero}}>
|
||||
<div class="containerName subhead" hero-id="title" flex {{detailHero}}>{{name}}</div>
|
||||
<div class="caption" style="margin-right: 8px">{{valueString totalValue}}</div>
|
||||
<div class="caption" style="margin-right: 8px">{{round totalWeight}}lbs</div>
|
||||
<paper-shadow class="card itemContainer"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="top {{colorClass}}"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<div class="subhead" flex
|
||||
hero-id="title" {{detailHero}}>
|
||||
{{name}}
|
||||
</div>
|
||||
<div class="caption" style="margin-right: 8px">
|
||||
{{valueString totalValue}}
|
||||
</div>
|
||||
<div class="caption" style="margin-right: 8px">
|
||||
{{round totalWeight}}lbs
|
||||
</div>
|
||||
<core-tooltip label="Container carried" position="left">
|
||||
<paper-checkbox class="carriedCheckbox" checked={{isCarried}}></paper-checkbox>
|
||||
<paper-checkbox class="carriedCheckbox"
|
||||
checked={{isCarried}}>
|
||||
</paper-checkbox>
|
||||
</core-tooltip>
|
||||
</div>
|
||||
<div flex class="containerMain">
|
||||
<div class="bottom list">
|
||||
{{#each items ../_id _id}}
|
||||
{{>inventoryItem}}
|
||||
{{/each}}
|
||||
@@ -78,18 +129,44 @@
|
||||
<div class="fab-buffer"></div>
|
||||
</div>
|
||||
{{#if canEditCharacter _id}}
|
||||
<paper-fab-menu id="inventoryAddMenu" icon="add" closeIcon="close" duration="0.3">
|
||||
<paper-fab-menu-item id="addItem" icon="note-add" color="#d23f31" tooltip="Item"></paper-fab-menu-item>
|
||||
<paper-fab-menu-item id="addContainer" icon="work" color="#d23f31" tooltip="Container"></paper-fab-menu-item>
|
||||
</paper-fab-menu>
|
||||
{{#fabMenu}}
|
||||
<core-tooltip label="New container" position="left">
|
||||
<paper-fab icon="work"
|
||||
class="addContainer"
|
||||
mini>
|
||||
</paper-fab>
|
||||
</core-tooltip>
|
||||
<core-tooltip label="New item" position="left">
|
||||
<paper-fab icon="note-add"
|
||||
class="addItem"
|
||||
mini>
|
||||
</paper-fab>
|
||||
</core-tooltip>
|
||||
{{/fabMenu}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="inventoryItem">
|
||||
<div class="itemSlot">
|
||||
<paper-item class="inventoryItem {{hidden}}" hero-id="main" noink {{detailHero}} layout horizontal draggable="true">
|
||||
{{#if ne1 quantity}}{{quantity}} {{/if}}{{pluralName}}
|
||||
</paper-item>
|
||||
<div class="item-slot">
|
||||
<div class="item {{hidden}} inventoryItem"
|
||||
hero-id="main" {{detailHero}}
|
||||
layout horizontal center
|
||||
draggable="true">
|
||||
<div flex class="itemName">
|
||||
{{#if ne1 quantity}}{{quantity}} {{/if}}{{pluralName}}
|
||||
</div>
|
||||
{{#if settings.showIncrement}}
|
||||
<div class="incrementButtons">
|
||||
<paper-icon-button class="addItemQuantity"
|
||||
icon="add"
|
||||
style="margin-right: -8px"></paper-icon-button>
|
||||
<paper-icon-button class="subItemQuantity"
|
||||
disabled={{lt1 quantity}}
|
||||
icon="remove"
|
||||
style="margin-right: -8px"></paper-icon-button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -61,6 +61,18 @@ Template.inventory.helpers({
|
||||
});
|
||||
return weight;
|
||||
},
|
||||
encumberedBuffs: function(){
|
||||
return Buffs.find({
|
||||
charId: this._id,
|
||||
type: "inate",
|
||||
name: {$in: [
|
||||
"Encumbered",
|
||||
"Heavily encumbered",
|
||||
"Over encumbered",
|
||||
"Can't move load",
|
||||
]},
|
||||
});
|
||||
},
|
||||
equipmentValue: function(){
|
||||
var value = 0;
|
||||
Items.find(
|
||||
@@ -103,7 +115,7 @@ Template.inventory.helpers({
|
||||
});
|
||||
|
||||
Template.inventory.events({
|
||||
"tap #addItem": function(event){
|
||||
"tap .addItem": function(event){
|
||||
var charId = this._id;
|
||||
Items.insert({
|
||||
charId: charId,
|
||||
@@ -120,7 +132,7 @@ Template.inventory.events({
|
||||
});
|
||||
});
|
||||
},
|
||||
"tap #addContainer": function(event){
|
||||
"tap .addContainer": function(event){
|
||||
var containerId = Containers.insert({
|
||||
name: "New Container",
|
||||
isCarried: true,
|
||||
@@ -136,6 +148,23 @@ Template.inventory.events({
|
||||
heroId: containerId,
|
||||
});
|
||||
},
|
||||
"tap .weightCarried": function(event) {
|
||||
var charId = this._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "carryDialog",
|
||||
data: {charId: charId, color: "green"},
|
||||
heroId: charId + "weightCarried",
|
||||
});
|
||||
},
|
||||
"tap .buff": function(event){
|
||||
var buffId = this._id;
|
||||
var charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "buffDialog",
|
||||
data: {buffId: buffId, charId: charId},
|
||||
heroId: buffId,
|
||||
});
|
||||
},
|
||||
"tap .inventoryItem": function(event){
|
||||
var itemId = this._id;
|
||||
var charId = Template.parentData()._id;
|
||||
@@ -145,7 +174,32 @@ Template.inventory.events({
|
||||
heroId: itemId,
|
||||
});
|
||||
},
|
||||
"tap .containerTop": function(event){
|
||||
"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) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
"tap .addItemQuantity": function(event) {
|
||||
var itemId = this._id;
|
||||
Items.update(itemId, {$set: {quantity: this.quantity + 1}});
|
||||
},
|
||||
"tap .subItemQuantity": function(event) {
|
||||
var itemId = this._id;
|
||||
Items.update(itemId, {$set: {quantity: this.quantity - 1}});
|
||||
},
|
||||
"tap .itemContainer .top": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "containerDialog",
|
||||
data: {containerId: this._id, charId: this.charId},
|
||||
@@ -167,6 +221,9 @@ Template.inventoryItem.helpers({
|
||||
ne1: function(num){
|
||||
return num !== 1;
|
||||
},
|
||||
lt1: function(num) {
|
||||
return num < 1;
|
||||
},
|
||||
hidden: function(){
|
||||
return Session.equals("inventory.dragItemId", this._id) ? "hidden" : null;
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</div>
|
||||
{{#if description}}
|
||||
<hr class="vertMargin">
|
||||
<div class="prewrap">{{description}}</div>
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
{{/if}}
|
||||
{{> effectsViewList charId=charId parentId=_id}}
|
||||
{{> attacksViewList charId=charId parentId=_id}}
|
||||
@@ -28,10 +28,25 @@
|
||||
<template name="itemEdit">
|
||||
<paper-input class="fullwidth" id="itemNameInput" label="Name" floatinglabel value={{name}}></paper-input>
|
||||
<div layout horizontal wrap>
|
||||
<paper-input-decorator label="Quantity" floatinglabel>
|
||||
<input id="quantityInput" type="number" value={{quantity}}>
|
||||
<paper-input-decorator label="Quantity"
|
||||
floatinglabel
|
||||
style="width: 80px">
|
||||
<input id="quantityInput"
|
||||
type="number"
|
||||
value={{quantity}}>
|
||||
</paper-input-decorator>
|
||||
{{# if ne1 quantity}}<paper-input flex id="itemPluralInput" label="Plural Name" floatinglabel value={{plural}}></paper-input>{{/if}}
|
||||
{{# if ne1 quantity}}
|
||||
<paper-input flex id="itemPluralInput"
|
||||
label="Plural Name"
|
||||
floatinglabel
|
||||
value={{plural}}></paper-input>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div center horizontal layout>
|
||||
<div class="padded">Show increment buttons</div>
|
||||
<paper-checkbox id="incrementCheckbox"
|
||||
checked={{settings.showIncrement}}>
|
||||
</paper-checkbox>
|
||||
</div>
|
||||
|
||||
<hr class="vertMargin">
|
||||
@@ -53,7 +68,9 @@
|
||||
</div>
|
||||
<div center horizontal layout>
|
||||
<div class="padded">Requires Attunement</div>
|
||||
<paper-checkbox id="attunementCheckbox" checked={{requiresAttunement}}></paper-checkbox>
|
||||
<paper-checkbox id="attunementCheckbox"
|
||||
checked={{requiresAttunement}}>
|
||||
</paper-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ Template.itemEdit.onRendered(function(){
|
||||
Template.itemEdit.helpers({
|
||||
ne1: function(num){
|
||||
return num != 1;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.itemEdit.events({
|
||||
@@ -87,6 +87,10 @@ Template.itemEdit.events({
|
||||
Meteor.call("unequipItem", this._id, this.charId);
|
||||
}
|
||||
},
|
||||
"change #incrementCheckbox": function(event){
|
||||
var value = event.currentTarget.checked;
|
||||
Items.update(this._id, {$set: {"settings.showIncrement": value}});
|
||||
},
|
||||
"change #attunementCheckbox": function(event){
|
||||
var value = event.currentTarget.checked;
|
||||
Items.update(this._id, {$set: {requiresAttunement: value}});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -3,6 +3,9 @@ Template.classDialog.onRendered(function(){
|
||||
});
|
||||
|
||||
Template.classDialog.events({
|
||||
"color-change": function(event, instance){
|
||||
Classes.update(instance.data.classId, {$set: {color: event.color}});
|
||||
},
|
||||
"tap #deleteButton": function(event, instance){
|
||||
Classes.softRemoveNode(instance.data.classId);
|
||||
GlobalUI.deletedToast(instance.data.classId, "Classes", "Class");
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
<template name="experienceDialog">
|
||||
{{#with experience}}
|
||||
{{#baseDialog title=name class=colorClass hideColor="true" startEditing=../startEditing}}
|
||||
{{#baseDialog title=name class=color hideColor="true" startEditing=../startEditing}}
|
||||
<div horizontal layout center-justified class= "display2">
|
||||
{{value}}
|
||||
</div>
|
||||
{{#if description}}
|
||||
<hr class="vertMargin">
|
||||
<div class="prewrap">{{description}}</div>
|
||||
<div class="pre-wrap">{{description}}</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<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>
|
||||
{{> experienceEdit}}
|
||||
{{/baseDialog}}
|
||||
{{/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,6 +1,15 @@
|
||||
Template.experienceEdit.onRendered(function(){
|
||||
updatePolymerInputs(this);
|
||||
});
|
||||
|
||||
Template.experienceDialog.helpers({
|
||||
feature: function(){
|
||||
return Features.findOne(this.featureId);
|
||||
experience: function(){
|
||||
Experiences.findOne(this.experienceId);
|
||||
return Experiences.findOne(this.experienceId);
|
||||
},
|
||||
color: function() {
|
||||
var char = Characters.findOne(this.charId, {fields: {color: 1}});
|
||||
if (char) return getColorClass(char.color);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -13,8 +22,10 @@ Template.experienceDialog.events({
|
||||
);
|
||||
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;
|
||||
Experiences.update(this._id, {$set: {name: value}});
|
||||
},
|
||||
@@ -27,10 +38,3 @@ Template.experienceDialog.events({
|
||||
Experiences.update(this._id, {$set: {description: value}});
|
||||
},
|
||||
});
|
||||
|
||||
Template.experienceDialog.helpers({
|
||||
experience: function(){
|
||||
Experiences.findOne(this.experienceId);
|
||||
return Experiences.findOne(this.experienceId);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,67 +1,91 @@
|
||||
<template name="journal">
|
||||
<div fit>
|
||||
<div id="journal" class="scroll-y" fit>
|
||||
<div class="containers">
|
||||
<div class="column-container">
|
||||
<!--Experience Table-->
|
||||
<paper-shadow class="card container experiencesCard" hero-id="main" {{detailHero}}>
|
||||
<div class="whiteTop" hero-id="toolbar" layout horizontal center {{detailHero}}>
|
||||
<div class="containerName subhead" flex>Experience</div>
|
||||
<div class="subhead">{{experience}} XP</div>
|
||||
<paper-shadow class="card experiencesCard"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="top white subhead"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<div flex>Experience</div>
|
||||
<div >{{characterCalculate "experience" _id}} XP</div>
|
||||
<paper-icon-button class="black54" id="addXP" icon="add"></paper-icon-button>
|
||||
</div>
|
||||
<div class="containerMain experiences">
|
||||
<div class="bottom list">
|
||||
{{#each experiences}}
|
||||
<div class="itemSlot">
|
||||
<paper-item class="inventoryItem experience" hero-id="main" {{detailHero}} layout horizontal>
|
||||
<div flex>{{name}}</div><div class="xpValue">{{value}}</div>
|
||||
</paper-item>
|
||||
<div class="item-slot">
|
||||
<div class="item experience"
|
||||
hero-id="main" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<div flex>{{name}}</div>
|
||||
<div class="xpValue">{{value}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if moreExperiencesOrCollapse}}
|
||||
<div class="containerFoot" layout="" horizontal="" center="" end-justified="">
|
||||
<paper-button id="moreExperiences" disabled={{notMoreExperiences}}>Load More</paper-button>
|
||||
<paper-button id="lessExperiences" disabled={{cantCollapse}}>Collapse</paper-button>
|
||||
<div layout horizontal center end-justified>
|
||||
<paper-button id="moreExperiences"
|
||||
disabled={{notMoreExperiences}}>
|
||||
Load More
|
||||
</paper-button>
|
||||
<paper-button id="lessExperiences"
|
||||
disabled={{cantCollapse}}>
|
||||
Collapse
|
||||
</paper-button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</paper-shadow>
|
||||
<!--Class Table-->
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
|
||||
<div class="whiteTop" hero-id="toolbar" layout horizontal center {{detailHero}}>
|
||||
<paper-shadow class="card"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="white top"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<div flex>
|
||||
<div class="containerName subhead">Level {{level}}</div>
|
||||
<div class="containerName subhead">
|
||||
Level {{characterCalculate "level" _id}}
|
||||
</div>
|
||||
{{#if nextLevelXP}}
|
||||
<div class="caption">
|
||||
Next Level: {{nextLevelXP}}XP
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<paper-icon-button class="black54" id="addClassButton" icon="add"></paper-icon-button>
|
||||
<paper-icon-button class="black54"
|
||||
id="addClassButton"
|
||||
icon="add">
|
||||
</paper-icon-button>
|
||||
</div>
|
||||
<div class="containerMain experiences">
|
||||
<div class="itemSlot">
|
||||
<paper-item class="inventoryItem race" hero-id="main" {{detailHero "race" _id}} layout horizontal>
|
||||
<div class="bottom list">
|
||||
<div class="item-slot">
|
||||
<div class="item race"
|
||||
hero-id="main" {{detailHero "race" _id}}
|
||||
layout horizontal center>
|
||||
{{race}}
|
||||
</paper-item>
|
||||
</div>
|
||||
</div>
|
||||
{{#each classes}}
|
||||
<div class="itemSlot">
|
||||
<paper-item class="inventoryItem class" hero-id="main" {{detailHero}} layout horizontal>
|
||||
<div class="item-slot">
|
||||
<div class="item class"
|
||||
hero-id="main" {{detailHero}}
|
||||
layout horizontal center>
|
||||
{{name}} {{level}}
|
||||
</paper-item>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
<!--Notes-->
|
||||
{{#each notes}}
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
|
||||
<div class="containerTop {{colorClass}} noteTop" hero-id="toolbar" layout horizontal center {{detailHero}}>
|
||||
<div flex>
|
||||
<div class="containerName subhead">{{name}}</div>
|
||||
</div>
|
||||
<paper-shadow class="card" hero-id="main" {{detailHero}}>
|
||||
<div class="top {{colorClass}} noteTop subhead"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
{{name}}
|
||||
</div>
|
||||
<div class="containerMain preline">{{description}}</div>
|
||||
<div class="bottom text">{{description}}</div>
|
||||
</paper-shadow>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@ Template.journal.helpers({
|
||||
return Levels.find({charId: charId, classId: this._id}, {sort: {value: 1}});
|
||||
},
|
||||
nextLevelXP: function(){
|
||||
var currentLevel = this.level();
|
||||
var currentLevel = Characters.calculate.level(this._id);
|
||||
if (currentLevel < 20){
|
||||
return XP_TABLE[currentLevel];
|
||||
}
|
||||
|
||||
@@ -1,18 +1,30 @@
|
||||
<template name="noteDialog">
|
||||
{{#with note}}
|
||||
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
|
||||
<div class="prewrap">{{description}}</div>
|
||||
<div class="pre-wrap">{{description}}</div>
|
||||
{{else}}
|
||||
<!--Name-->
|
||||
<div horizontal layout>
|
||||
<paper-input id="noteNameInput" label="Name" floatinglabel value={{name}} flex></paper-input>
|
||||
</div>
|
||||
<!--Description-->
|
||||
<paper-input-decorator label="Description" floatinglabel layout vertical>
|
||||
<paper-autogrow-textarea>
|
||||
<textarea id="noteDescriptionInput" value={{description}}></textarea>
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
{{> noteDialogEdit}}
|
||||
{{/baseDialog}}
|
||||
{{/with}}
|
||||
</template>
|
||||
|
||||
<template name="noteDialogEdit">
|
||||
<!--Name-->
|
||||
<div horizontal layout>
|
||||
<paper-input id="noteNameInput"
|
||||
label="Name"
|
||||
floatinglabel
|
||||
value={{name}}
|
||||
flex>
|
||||
</paper-input>
|
||||
</div>
|
||||
<!--Description, formatting this nicely breaks it, leave it as is-->
|
||||
<paper-input-decorator label="Description"
|
||||
floatinglabel
|
||||
layout vertical>
|
||||
<paper-autogrow-textarea>
|
||||
<textarea id="noteDescriptionInput"
|
||||
value={{description}}></textarea>
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
</template>
|
||||
@@ -1,5 +1,7 @@
|
||||
Template.noteDialog.onRendered(function(){
|
||||
updatePolymerInputs(this);
|
||||
Template.noteDialog.helpers({
|
||||
note: function(){
|
||||
return Notes.findOne(this.noteId);
|
||||
}
|
||||
});
|
||||
|
||||
Template.noteDialog.events({
|
||||
@@ -11,6 +13,13 @@ Template.noteDialog.events({
|
||||
GlobalUI.deletedToast(instance.data.noteId, "Notes", "Note");
|
||||
GlobalUI.closeDetail();
|
||||
},
|
||||
});
|
||||
|
||||
Template.noteDialogEdit.onRendered(function(){
|
||||
updatePolymerInputs(this);
|
||||
});
|
||||
|
||||
Template.noteDialogEdit.events({
|
||||
"change #noteNameInput, input #noteNameInput": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
Notes.update(this._id, {$set: {name: value}});
|
||||
@@ -20,9 +29,3 @@ Template.noteDialog.events({
|
||||
Notes.update(this._id, {$set: {description: value}});
|
||||
},
|
||||
});
|
||||
|
||||
Template.noteDialog.helpers({
|
||||
note: function(){
|
||||
return Notes.findOne(this.noteId);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template name="raceDialog">
|
||||
{{#baseDialog title="Race" class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
|
||||
{{#baseDialog title="Race" class=color hideColor="true" hideDelete="true" startEditing=startEditing}}
|
||||
<div horizontal layout center-justified class= "display2">
|
||||
{{race}}
|
||||
</div>
|
||||
|
||||
@@ -13,5 +13,9 @@ Template.raceDialog.helpers({
|
||||
race: function(){
|
||||
var char = Characters.findOne(this.charId, {fields: {race: 1}});
|
||||
return char && char.race;
|
||||
}
|
||||
},
|
||||
color: function() {
|
||||
var char = Characters.findOne(this.charId, {fields: {color: 1}});
|
||||
if (char) return getColorClass(char.color);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<template name="backgroundDialog">
|
||||
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
|
||||
<div class="pre-wrap">{{evaluateString charId value}}</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,7 +1,7 @@
|
||||
<template name="persona">
|
||||
<div fit>
|
||||
<div id="persona" class="scroll-y" fit>
|
||||
<div class="containers">
|
||||
<div class="column-container">
|
||||
{{#with characterDetails}}
|
||||
{{#containerCardHelper this}}{{alignment}} {{gender}} {{race}}{{/containerCardHelper}}
|
||||
{{/with}}
|
||||
@@ -11,11 +11,11 @@
|
||||
{{> containerCard characterField "bonds" "Bonds"}}
|
||||
{{> containerCard characterField "flaws" "Flaws"}}
|
||||
{{> containerCard characterField "backstory" "Background"}}
|
||||
<paper-shadow class="card container">
|
||||
<div class="containerTop whiteTop" layout horizontal center>
|
||||
<div class="containerName subhead" flex>Languages</div>
|
||||
<paper-shadow class="card">
|
||||
<div class="white top subhead">
|
||||
Languages
|
||||
</div>
|
||||
<div flex class="containerMain listPadded">
|
||||
<div class="bottom list">
|
||||
{{#each languages}}
|
||||
{{> proficiencyListItem}}
|
||||
{{/each}}
|
||||
@@ -27,14 +27,19 @@
|
||||
</template>
|
||||
|
||||
<template name="containerCard">
|
||||
{{#containerCardHelper this}}{{body}}{{/containerCardHelper}}
|
||||
{{#containerCardHelper this}}{{evaluateString _id body}}{{/containerCardHelper}}
|
||||
</template>
|
||||
|
||||
<template name="containerCardHelper">
|
||||
<paper-shadow class="card container {{class}}" hero-id="main" {{detailHero field ../_id}}>
|
||||
<div class="containerTop {{colorClass}} {{topClass}}" hero-id="toolbar" layout horizontal center {{detailHero field ../_id}}>
|
||||
<div class="containerName subhead" hero-id="title" flex {{detailHero field ../_id}}>{{title}}</div>
|
||||
<paper-shadow class="card {{class}}"
|
||||
hero-id="main" {{detailHero field ../_id}}>
|
||||
<div class="top subhead {{colorClass}} {{topClass}}"
|
||||
hero-id="toolbar" {{detailHero field ../_id}}>
|
||||
<div class="subhead" flex
|
||||
hero-id="title" {{detailHero field ../_id}}>
|
||||
{{title}}
|
||||
</div>
|
||||
</div>
|
||||
<div flex class="containerMain prewrap">{{> UI.contentBlock}}</div>
|
||||
<div class="bottom text">{{> UI.contentBlock}}</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
@@ -40,11 +40,20 @@ Template.persona.helpers({
|
||||
|
||||
Template.persona.events({
|
||||
"tap .characterField": function(event){
|
||||
if (this.field !== "details"){
|
||||
if (this.field === "details"){
|
||||
this.charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "personaDetailsDialog",
|
||||
data: this,
|
||||
heroId: this._id + this.field,
|
||||
});
|
||||
} else {
|
||||
var template = "textDialog";
|
||||
if (this.field === "backstory") template = "backgroundDialog";
|
||||
var charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "textDialog",
|
||||
data: {
|
||||
template: template,
|
||||
data: {
|
||||
charId: charId,
|
||||
field: this.field,
|
||||
title: this.title,
|
||||
@@ -52,13 +61,6 @@ Template.persona.events({
|
||||
},
|
||||
heroId: this._id + this.field,
|
||||
});
|
||||
} else {
|
||||
this.charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "personaDetailsDialog",
|
||||
data: this,
|
||||
heroId: this._id + this.field,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template name="textDialog">
|
||||
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
|
||||
<div class="prewrap">{{value}}</div>
|
||||
<div class="pre-wrap">{{evaluateString charId value}}</div>
|
||||
{{else}}
|
||||
{{> textDialogEdit}}
|
||||
{{/baseDialog}}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<template name="proficiencyListItem">
|
||||
<div class="itemSlot">
|
||||
<paper-item noink class="white proficiencyItem" hero-id="main" {{detailHero}}>
|
||||
<core-icon icon="{{profIcon}}" class="black54"></core-icon>
|
||||
<div class="sideMargin">{{getName}}</div>
|
||||
</paper-item>
|
||||
<div class="item-slot">
|
||||
<div class="proficiency item small"
|
||||
hero-id="main" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<core-icon icon="{{profIcon}}"
|
||||
style="margin-right: 16px;"></core-icon>
|
||||
<div flex>{{getName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -14,7 +14,7 @@ Template.proficiencyListItem.helpers({
|
||||
});
|
||||
|
||||
Template.proficiencyListItem.events({
|
||||
"tap .proficiencyItem": function(event, instance){
|
||||
"tap .proficiency": function(event, instance){
|
||||
openParentDialog(this.parent, this.charId, this._id);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template name="proficiencyView">
|
||||
<div class="proficiencyView" layout horizontal center>
|
||||
<core-icon icon="{{profIcon}}"></core-icon>
|
||||
<div class="sideMargin">{{getName}}</div>
|
||||
<div class="proficiencyView item small"
|
||||
style="padding: 0;"
|
||||
layout horizontal center>
|
||||
<core-icon icon="{{profIcon}}" style="margin-right: 16px;"></core-icon>
|
||||
<div>{{getName}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{{#if proficiencies.count}}
|
||||
<hr class="vertMargin">
|
||||
<div class="proficiencies">
|
||||
<h2 class="spaceAfter">Proficiencies</h2>
|
||||
<h2 style="margin-bottom: 8px;">Proficiencies</h2>
|
||||
{{#each proficiencies}}
|
||||
{{> proficiencyView}}
|
||||
{{/each}}
|
||||
|
||||
@@ -9,24 +9,33 @@
|
||||
</template>
|
||||
|
||||
<template name="spellDetails">
|
||||
<div class="caption">
|
||||
<div class="body2">
|
||||
Level {{level}} {{school}}, {{preparedString}}
|
||||
</div>
|
||||
<div class="vertMargin">
|
||||
<div style="margin: 16px 0 16px 0;">
|
||||
{{#if castingTime}}
|
||||
<div>
|
||||
<span class="body2">Casting Time: </span><span>{{castingTime}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if range}}
|
||||
<div>
|
||||
<span class="body2">Range: </span><span>{{range}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if getComponents}}
|
||||
<div>
|
||||
<span class="body2">Components: </span><span>{{getComponents}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if duration}}
|
||||
<div>
|
||||
<span class="body2">Duration: </span><span>{{duration}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="prewrap">{{description}}</div>
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
{{> attacksViewList charId=charId parentId=_id}}
|
||||
</template>
|
||||
|
||||
<template name="spellEdit">
|
||||
@@ -126,4 +135,5 @@
|
||||
<textarea id="descriptionInput" placeholder value={{description}}></textarea>
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
{{> attackEditList parentId=_id parentCollection="Spells" charId=charId enabled=true name=name}}
|
||||
</template>
|
||||
@@ -20,7 +20,7 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
<hr class="vertMargin">
|
||||
<div class="prewrap">{{description}}</div>
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<!--Name-->
|
||||
|
||||
@@ -1,84 +1,120 @@
|
||||
<template name="spells">
|
||||
<div fit>
|
||||
<div id="spells" class="scroll-y" fit>
|
||||
<div class="spellsContainer" layout horizontal start wrap>
|
||||
<div style="padding: 4px;"
|
||||
layout horizontal start wrap>
|
||||
{{#if hasSlots}}
|
||||
<paper-shadow class="card container spellSlotContainer" hero-id="main" {{detailHero}}>
|
||||
<div class="containerTop whiteTop" layout horizontal center>
|
||||
<div class="containerName subhead" hero-id="title" flex>Spell Slots</div>
|
||||
<paper-shadow class="card"
|
||||
style="margin: 4px;"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="white top subhead"
|
||||
layout horizontal center>
|
||||
Spell Slots
|
||||
</div>
|
||||
<div flex class="containerMain">
|
||||
<div class="bottom list">
|
||||
{{#each levels}}{{#if showSlots ..}}
|
||||
<div class="itemSlot">
|
||||
<paper-item class="inventoryItem spellSlot" hero-id="main" {{detailHero slotStatName ../_id}} layout horizontal>
|
||||
<div class="slotName">
|
||||
<div class="item-slot">
|
||||
<div class="item spellSlot"
|
||||
hero-id="main" {{detailHero slotStatName ../_id}}
|
||||
layout horizontal center>
|
||||
<div style="margin-right: 16px">
|
||||
{{name}}
|
||||
</div>
|
||||
<div flex layout horizontal center>
|
||||
{{#each slotBubbles ..}}
|
||||
<paper-icon-button class="slotBubble" icon={{icon}} disabled={{disabled}}></paper-icon-button>
|
||||
<paper-icon-button class="slotBubble"
|
||||
icon={{icon}}
|
||||
disabled={{disabled}}>
|
||||
</paper-icon-button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-item>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
{{/if}}
|
||||
{{#each spellLists}}
|
||||
<paper-shadow class="card container spellList" hero-id="main" {{detailHero}} flex>
|
||||
<div class="containerTop {{colorClass}}" hero-id="toolbar" layout horizontal center {{detailHero}}>
|
||||
<paper-shadow class="card spellList" flex
|
||||
hero-id="main" {{detailHero}}
|
||||
style="margin: 4px;">
|
||||
<div class="top {{colorClass}}"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<div flex>
|
||||
<div class="containerName subhead">{{name}}</div>
|
||||
<div class="subhead">{{name}}</div>
|
||||
<div class="caption">
|
||||
{{#if saveDC}}
|
||||
Save DC: {{evaluate charId saveDC}}
|
||||
<div style="width: 16px; display: inline-block;"></div>
|
||||
<span style="margin-right: 16px;">
|
||||
Save DC: {{evaluate charId saveDC}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{#if attackBonus}}
|
||||
Attack Bonus: {{evaluateSigned charId attackBonus}}
|
||||
<span>
|
||||
Attack Bonus: {{evaluateSigned charId attackBonus}}
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if settings.showUnprepared}}
|
||||
{{#if maxPrepared}}<div class="subhead">{{numPrepared}} / {{evaluate charId maxPrepared}}</div>{{/if}}
|
||||
<core-tooltip label="Done" position="left">
|
||||
<paper-icon-button class="finishPrep" icon="done"></paper-icon-button>
|
||||
</core-tooltip>
|
||||
{{#if maxPrepared}}
|
||||
<div class="subhead">
|
||||
{{numPrepared}} / {{evaluate charId maxPrepared}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<core-tooltip label="Done"
|
||||
position="left">
|
||||
<paper-icon-button class="finishPrep"
|
||||
icon="done">
|
||||
</paper-icon-button>
|
||||
</core-tooltip>
|
||||
{{else}}
|
||||
<core-tooltip label="Change prepared spells" position="left">
|
||||
<paper-icon-button class="prepSpells" icon="book"></paper-icon-button>
|
||||
<core-tooltip label="Change prepared spells"
|
||||
position="left">
|
||||
<paper-icon-button class="prepSpells"
|
||||
icon="book">
|
||||
</paper-icon-button>
|
||||
</core-tooltip>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="containerMain">
|
||||
<div class="bottom list column-container">
|
||||
{{#each levels}}
|
||||
<div class="spellLevel">
|
||||
{{#if spellCount .. ../../_id}}
|
||||
<div class="list-subhead" layout horizontal center>
|
||||
<div class="subhead">
|
||||
{{name}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#each spells ../_id ../../_id}}
|
||||
{{#if showSpell ../../settings.showUnprepared}}
|
||||
<div class="itemSlot">
|
||||
<paper-item class="inventoryItem spell" hero-id="main" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<!--disabled={{cantCast ../level ../../..}} to grey out spells above highest usable slot-->
|
||||
<div class="item-slot">
|
||||
<div class="tall spell item"
|
||||
hero-id="main" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<core-icon icon="social:whatshot"
|
||||
style="color: {{hexColor color}};"
|
||||
style="color: {{hexColor color}};
|
||||
margin-right: 16px;"
|
||||
></core-icon>
|
||||
<div flex layout vertical>
|
||||
<div>{{name}}</div>
|
||||
<div class="caption">
|
||||
{{school}} {{castingTime}}
|
||||
{{#if ritual}}(ritual){{/if}}{{#if spellComponents}} - {{spellComponents}}{{/if}}
|
||||
{{school}}
|
||||
{{castingTime}}
|
||||
{{#if ritual}}
|
||||
(ritual)
|
||||
{{/if}}
|
||||
{{#if spellComponents}}
|
||||
- {{spellComponents}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if ../../settings.showUnprepared}}
|
||||
<paper-checkbox class="preparedCheckbox" checked={{isPrepared}} disabled={{cantUnprepare}}></paper-checkbox>
|
||||
<paper-checkbox class="preparedCheckbox"
|
||||
checked={{isPrepared}}
|
||||
disabled={{cantUnprepare}}>
|
||||
</paper-checkbox>
|
||||
{{/if}}
|
||||
</paper-item>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
@@ -92,9 +128,19 @@
|
||||
</div>
|
||||
</div>
|
||||
{{#if canEditCharacter _id}}
|
||||
<paper-fab-menu id="inventoryAddMenu" icon="add" closeIcon="close" duration="0.3">
|
||||
<paper-fab-menu-item id="addSpell" icon="note-add" color="#d23f31" tooltip="Spell"></paper-fab-menu-item>
|
||||
<paper-fab-menu-item id="addSpellList" icon="work" color="#d23f31" tooltip="Spell List"></paper-fab-menu-item>
|
||||
</paper-fab-menu>
|
||||
{{#fabMenu}}
|
||||
<core-tooltip label="New spell list" position="left">
|
||||
<paper-fab icon="work"
|
||||
class="addSpellList"
|
||||
mini>
|
||||
</paper-fab>
|
||||
</core-tooltip>
|
||||
<core-tooltip label="New spell" position="left">
|
||||
<paper-fab icon="note-add"
|
||||
class="addSpell"
|
||||
mini>
|
||||
</paper-fab>
|
||||
</core-tooltip>
|
||||
{{/fabMenu}}
|
||||
{{/if}}
|
||||
</template>
|
||||
@@ -84,32 +84,28 @@ Template.spells.helpers({
|
||||
},
|
||||
cantCast: function(level, char){
|
||||
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 true;
|
||||
},
|
||||
baseSlots: function(char){
|
||||
return char.attributeBase("level" + this.level + "SpellSlots");
|
||||
},
|
||||
slots: function(char){
|
||||
return char.attributeValue("level" + this.level + "SpellSlots");
|
||||
},
|
||||
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(){
|
||||
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 false;
|
||||
},
|
||||
slotBubbles: function(char){
|
||||
var baseSlots = char.attributeBase("level" + this.level + "SpellSlots");
|
||||
var currentSlots = char.attributeValue("level" + this.level + "SpellSlots");
|
||||
var baseSlots = Characters.calculate.attributeBase(char._id, "level" + this.level + "SpellSlots");
|
||||
var currentSlots = Characters.calculate.attributeValue(char._id, "level" + this.level + "SpellSlots");
|
||||
var slotsUsed = baseSlots - currentSlots;
|
||||
var bubbles = [];
|
||||
var i;
|
||||
@@ -143,15 +139,15 @@ Template.spells.events({
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (event.currentTarget.icon === "radio-button-off"){
|
||||
if (
|
||||
char.attributeValue(this.attribute) <
|
||||
char.attributeBase(this.attribute)
|
||||
Characters.calculate.attributeValue(char._id, this.attribute) <
|
||||
Characters.calculate.attributeBase(char._id, this.attribute)
|
||||
){
|
||||
modifier = {$inc: {}};
|
||||
modifier.$inc[this.attribute + ".adjustment"] = 1;
|
||||
Characters.update(this.charId, modifier, {validate: false});
|
||||
}
|
||||
} else {
|
||||
if (char.attributeValue(this.attribute) > 0){
|
||||
if (Characters.calculate.attributeValue(char._id, this.attribute) > 0){
|
||||
modifier = {$inc: {}};
|
||||
modifier.$inc[this.attribute + ".adjustment"] = -1;
|
||||
Characters.update(this.charId, modifier, {validate: false});
|
||||
@@ -170,7 +166,7 @@ Template.spells.events({
|
||||
heroId: charId + stat,
|
||||
});
|
||||
},
|
||||
"tap .containerTop": function(event){
|
||||
"tap .spellList .top": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "spellListDialog",
|
||||
data: {spellListId: this._id, charId: this.charId},
|
||||
@@ -184,7 +180,7 @@ Template.spells.events({
|
||||
heroId: this._id,
|
||||
});
|
||||
},
|
||||
"tap #addSpellList": function(event){
|
||||
"tap .addSpellList": function(event){
|
||||
var charId = this.charId;
|
||||
SpellLists.insert({
|
||||
name: "New SpellList",
|
||||
@@ -201,7 +197,7 @@ Template.spells.events({
|
||||
}
|
||||
});
|
||||
},
|
||||
"tap #addSpell": function(event){
|
||||
"tap .addSpell": function(event){
|
||||
var charId = this.charId;
|
||||
var listId = SpellLists.findOne({charId: this._id})._id;
|
||||
Spells.insert({
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
.card.double {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.card.double > div{
|
||||
vertical-align: top;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.abilityScore {
|
||||
width: 70px;
|
||||
text-align: center;
|
||||
background-color: #D50000;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
#stats .card {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.abilityCardRight {
|
||||
flex-grow: 1;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.abilityCardRight hr{
|
||||
margin: 8px 0 8px -16px;
|
||||
}
|
||||
|
||||
.abilityCardRight h1{
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@@ -1,122 +1,14 @@
|
||||
<template name="abilityMiniCard">
|
||||
<paper-shadow class="card double abilityMiniCard"
|
||||
hero-id="main" {{detailHero ability ../_id}}>
|
||||
<div class="abilityScore white-text {{color}}"
|
||||
<paper-shadow class="card abilityMiniCard clickable"
|
||||
hero-id="main" {{detailHero ability ../_id}}
|
||||
layout horizontal>
|
||||
<div class="left white-text {{color}}"
|
||||
hero-id="toolbar" {{detailHero ability ../_id}}>
|
||||
<h1 class="display1">{{../attributeValue ability}}</h1>
|
||||
<h2>{{../abilityMod ability}}</h2>
|
||||
<div class="display1">{{characterCalculate "attributeValue" ../_id ability}}</div>
|
||||
<div class="title">{{abilityMod}}</div>
|
||||
</div>
|
||||
<div class="abilityCardRight subhead" layout horizontal center>
|
||||
<div class="right subhead" layout horizontal center>
|
||||
{{title}}
|
||||
</div>
|
||||
<paper-ripple fit></paper-ripple>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
|
||||
<template name="strengthCard">
|
||||
<paper-shadow class="card double">
|
||||
<div class="abilityScore red white-text">
|
||||
{{> ripple color="#eee"}}
|
||||
<h1 class="display1">{{attributeValue "strength"}}</h1>
|
||||
<h2>{{abilityMod "strength"}}</h2>
|
||||
</div>
|
||||
<div class="abilityCardRight">
|
||||
<h1>Strength</h1>
|
||||
{{> skillRow name="Save" skill="strengthSave"}}
|
||||
<hr>
|
||||
{{> skillRow name="Athletics" skill="athletics"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
|
||||
<template name="dexterityCard">
|
||||
<paper-shadow class="card double">
|
||||
<div class="abilityScore green white-text">
|
||||
{{> ripple color="#eee"}}
|
||||
<h1 class="display1">{{attributeValue "dexterity"}}</h1>
|
||||
<h2>{{abilityMod "dexterity"}}</h2>
|
||||
</div>
|
||||
<div class="abilityCardRight">
|
||||
<h1>Dexterity</h1>
|
||||
{{> skillRow name="Save" skill="dexteritySave"}}
|
||||
<hr>
|
||||
{{> skillRow name="Acrobatics" skill="acrobatics"}}
|
||||
{{> skillRow name="Sleight of Hand" skill="sleightOfHand"}}
|
||||
{{> skillRow name="Stealth" skill="stealth"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
|
||||
<template name="constitutionCard">
|
||||
<paper-shadow class="card double">
|
||||
<div class="abilityScore deep-orange white-text">
|
||||
{{> ripple color="#eee"}}
|
||||
<h1 class="display1">{{attributeValue "constitution"}}</h1>
|
||||
<h2>{{abilityMod "constitution"}}</h2>
|
||||
</div>
|
||||
<div class="abilityCardRight">
|
||||
<h1>Constitution</h1>
|
||||
{{> skillRow name="Save" skill="constitutionSave"}}
|
||||
<hr>
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
|
||||
<template name="intelligenceCard">
|
||||
<paper-shadow class="card double">
|
||||
<div class="abilityScore indigo white-text">
|
||||
{{> ripple color="#eee"}}
|
||||
<h1 class="display1">{{attributeValue "intelligence"}}</h1>
|
||||
<h2>{{abilityMod "intelligence"}}</h2>
|
||||
</div>
|
||||
<div class="abilityCardRight">
|
||||
<h1>Intelligence</h1>
|
||||
{{> skillRow name="Save" skill="intelligenceSave"}}
|
||||
<hr>
|
||||
{{> skillRow name="Arcana" skill="arcana"}}
|
||||
{{> skillRow name="History" skill="history"}}
|
||||
{{> skillRow name="Investigation" skill="investigation"}}
|
||||
{{> skillRow name="Nature" skill="nature"}}
|
||||
{{> skillRow name="Religion" skill="religion"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
|
||||
<template name="wisdomCard">
|
||||
<paper-shadow class="card double">
|
||||
<div class="abilityScore purple white-text">
|
||||
{{> ripple color="#eee"}}
|
||||
<h1 class="display1">{{attributeValue "wisdom"}}</h1>
|
||||
<h2>{{abilityMod "wisdom"}}</h2>
|
||||
</div>
|
||||
<div class="abilityCardRight">
|
||||
<h1>Wisdom</h1>
|
||||
{{> skillRow name="Save" skill="wisdomSave"}}
|
||||
<hr>
|
||||
{{> skillRow name="Animal Handling" skill="animalHandling"}}
|
||||
{{> skillRow name="Insight" skill="insight"}}
|
||||
{{> skillRow name="Medicine" skill="medicine"}}
|
||||
{{> skillRow name="Perception" skill="perception" showPassive="true"}}
|
||||
{{> skillRow name="Survival" skill="survival"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
|
||||
<template name="charismaCard">
|
||||
<paper-shadow class="card double">
|
||||
<div class="abilityScore pink white-text">
|
||||
{{> ripple color="#eee"}}
|
||||
<h1 class="display1">{{attributeValue "charisma"}}</h1>
|
||||
<h2>{{abilityMod "charisma"}}</h2>
|
||||
</div>
|
||||
<div class="abilityCardRight">
|
||||
<h1>Charisma</h1>
|
||||
{{> skillRow name="Save" skill="charismaSave"}}
|
||||
<hr>
|
||||
{{> skillRow name="Deception" skill="deception"}}
|
||||
{{> skillRow name="Intimidation" skill="intimidation"}}
|
||||
{{> skillRow name="Performance" skill="performance"}}
|
||||
{{> skillRow name="Persuasion" skill="persuasion"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
@@ -0,0 +1,9 @@
|
||||
Template.abilityMiniCard.helpers({
|
||||
abilityMod: function() {
|
||||
return signedString(
|
||||
Characters.calculate.abilityMod(
|
||||
Template.parentData()._id, this.ability
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- needs name, char, and statName -->
|
||||
<template name="attributeDialog">
|
||||
{{#baseDialog title=name class=colorClass hideEdit=true}}
|
||||
{{#baseDialog title=name class=color hideEdit=true}}
|
||||
{{> attributeDialogView}}
|
||||
{{/baseDialog}}
|
||||
</template>
|
||||
@@ -23,7 +23,7 @@
|
||||
{{#each baseEffects}}
|
||||
<tr>
|
||||
<td>{{sourceName}}</td>
|
||||
<td>{{signedString statValue}}</td>
|
||||
<td>Base: {{statValue}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{#each addEffects}}
|
||||
@@ -35,7 +35,7 @@
|
||||
{{#each mulEffects}}
|
||||
<tr>
|
||||
<td>{{sourceName}}</td>
|
||||
<td>×{{statValue}}</td>
|
||||
<td>× {{statValue}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{#each minEffects}}
|
||||
|
||||
@@ -93,51 +93,53 @@ var abilities = {
|
||||
charisma: {name: "Charisma"},
|
||||
};
|
||||
|
||||
Template.attributeDialog.helpers({
|
||||
color: function(){
|
||||
if (this.color) return this.color + " white-text";
|
||||
var char = Characters.findOne(this.charId, {fields: {color: 1}});
|
||||
if (char) return getColorClass(char.color);
|
||||
},
|
||||
});
|
||||
|
||||
Template.attributeDialogView.helpers({
|
||||
or: function(a, b, c){
|
||||
return a || b || c;
|
||||
},
|
||||
adjustment: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
var value = char.attributeValue(this.statName);
|
||||
var base = char.attributeBase(this.statName);
|
||||
var value = Characters.calculate.attributeValue(this.charId, this.statName);
|
||||
var base = Characters.calculate.attributeBase(this.charId, this.statName);
|
||||
return value - base;
|
||||
},
|
||||
baseEffects: function(){
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "base"}
|
||||
{charId: this.charId, stat: this.statName, operation: "base", enabled: true}
|
||||
);
|
||||
},
|
||||
addEffects: function(){
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "add"}
|
||||
{charId: this.charId, stat: this.statName, operation: "add", enabled: true}
|
||||
);
|
||||
},
|
||||
mulEffects: function(){
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "mul"}
|
||||
{charId: this.charId, stat: this.statName, operation: "mul", enabled: true}
|
||||
);
|
||||
},
|
||||
minEffects: function(){
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "min"}
|
||||
{charId: this.charId, stat: this.statName, operation: "min", enabled: true}
|
||||
);
|
||||
},
|
||||
maxEffects: function(){
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "max"}
|
||||
{charId: this.charId, stat: this.statName, operation: "max", enabled: true}
|
||||
);
|
||||
},
|
||||
attributeBase: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) throw "character is " + char;
|
||||
return char.attributeBase(this.statName);
|
||||
return Characters.calculate.attributeBase(this.charId, this.statName);
|
||||
},
|
||||
attributeValue: function() {
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) throw "character is " + char;
|
||||
return char.attributeValue(this.statName);
|
||||
return Characters.calculate.attributeValue(this.charId, this.statName);
|
||||
},
|
||||
sourceName: function(){
|
||||
if (this.parent.group === "racial"){
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<template name="strengthDialog">
|
||||
{{#baseDialog title=name class=color hideEdit=true}}
|
||||
{{> attributeDialogView}}
|
||||
<hr class="vertMargin">
|
||||
<div>
|
||||
<div class="title padded">Carrying</div>
|
||||
{{> carryCapacityTable}}
|
||||
<div class="title padded">Jumping</div>
|
||||
<table class="strengthTable">
|
||||
<tr>
|
||||
<td>Running long jump</td>
|
||||
<td>{{evaluate charId "strength"}} feet</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Standing long jump</td>
|
||||
<td>{{evaluate charId "floor(strength/2)"}} feet</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Running high jump</td>
|
||||
<td>{{evaluate charId "3 + strengthMod"}} feet</td>
|
||||
<td class="caption">
|
||||
Can reach a ledge as high as
|
||||
{{evaluate charId "3 + strengthMod"}} feet
|
||||
+ 1.5× your height
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Standing high jump</td>
|
||||
<td>{{evaluate charId "floor((3 + strengthMod)/2)"}} feet</td>
|
||||
<td class="caption">
|
||||
Can reach a ledge as high as
|
||||
{{evaluate charId "floor((3 + strengthMod)/2)"}} feet
|
||||
+ 1.5× your height
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{{/baseDialog}}
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
Template.strengthDialog.helpers({
|
||||
color: function(){
|
||||
if (this.color) return this.color + " white-text";
|
||||
var char = Characters.findOne(this.charId, {fields: {color: 1}});
|
||||
if (char) return getColorClass(char.color);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
<template name="carryCapacityTable">
|
||||
<table class="carryCapacityTable strengthTable">
|
||||
<tr>
|
||||
<td>Encumbered</td>
|
||||
<td>>{{evaluate charId "strength * 5"}}lbs</td>
|
||||
<td class="caption">Variant rule, encumbered characters move 10 feet slower</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Heavily encumbered</td>
|
||||
<td>>{{evaluate charId "strength * 10"}}lbs</td>
|
||||
<td class="caption">
|
||||
Variant rule, heavily encumbered characters move 20 feet slower and have disadvantage on ability checks, attack rolls, and saving thows that use Strength, Dexterity, or Constitution
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Over Encumbered</td>
|
||||
<td>>{{evaluate charId "strength * 15"}}lbs</td>
|
||||
<td class="caption">
|
||||
Characters that can only just lift, push or drag their current load can only move at 5 feet.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Push, drag or lift maximum</td>
|
||||
<td>{{evaluate charId "strength * 30"}}lbs</td>
|
||||
<td class="caption"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</template>
|
||||
@@ -1,4 +1,4 @@
|
||||
.healthCard paper-slider{
|
||||
.healthCard paper-diff-slider{
|
||||
width: 100%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
@@ -2,30 +2,32 @@
|
||||
<paper-shadow class="card container healthCard"
|
||||
hero-id="main" {{detailHero "hitPoints" _id}}
|
||||
layout horizontal wrap>
|
||||
<div class="green white-text subhead padded leftRound"
|
||||
<div class="green white-text subhead left"
|
||||
hero-id="toolbar" {{detailHero "hitPoints" _id}}
|
||||
layout vertical center>
|
||||
layout vertical center center-justified>
|
||||
<div class="hitPointTitle clickable">Hit Points</div>
|
||||
<paper-icon-button class="white54" id="addTempHP" icon="add"></paper-icon-button>
|
||||
</div>
|
||||
<div class="padded" flex layout vertical center-justified style="min-width: 180px;">
|
||||
<paper-slider id="hitPointSlider"
|
||||
value={{attributeValue "hitPoints"}}
|
||||
max={{attributeBase "hitPoints"}}
|
||||
editable pin
|
||||
role="slider"
|
||||
></paper-slider>
|
||||
<div class="right" flex layout vertical center-justified style="min-width: 180px;">
|
||||
<div layout horizontal>
|
||||
<paper-diff-slider id="hitPointSlider"
|
||||
value={{characterCalculate "attributeValue" _id "hitPoints"}}
|
||||
max={{characterCalculate "attributeBase" _id "hitPoints"}}
|
||||
editable pin
|
||||
role="slider">
|
||||
</paper-diff-slider>
|
||||
</div>
|
||||
{{#each tempHitPoints}}
|
||||
<div>
|
||||
{{name}}
|
||||
<div layout horizontal>
|
||||
<paper-slider class="tempHitPointSlider"
|
||||
<paper-diff-slider class="tempHitPointSlider"
|
||||
value={{left}}
|
||||
max={{maximum}}
|
||||
editable pin
|
||||
role="slider"
|
||||
flex
|
||||
></paper-slider>
|
||||
></paper-diff-slider>
|
||||
{{#unless left}}{{#unless deleteOnZero}}
|
||||
<paper-icon-button class="deleteTHP" icon="delete"></paper-icon-button>
|
||||
{{/unless}}{{/unless}}
|
||||
@@ -33,9 +35,21 @@
|
||||
</div>
|
||||
{{/each}}
|
||||
<div class="caption">
|
||||
{{#if multipliers.immunities.length}} <div>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}}
|
||||
{{#if multipliers.immunities.length}}
|
||||
<div>
|
||||
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>
|
||||
{{#if showDeathSave}}
|
||||
{{#with deathSaveObject}}
|
||||
|
||||
@@ -3,7 +3,7 @@ Template.healthCard.helpers({
|
||||
return TemporaryHitPoints.find({charId: this._id});
|
||||
},
|
||||
showDeathSave: function(){
|
||||
return this.attributeValue("hitPoints") <= 0;
|
||||
return Characters.calculate.attributeValue(this._id, "hitPoints") <= 0;
|
||||
},
|
||||
deathSaveObject: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {deathSave: 1}});
|
||||
@@ -27,21 +27,20 @@ Template.healthCard.helpers({
|
||||
return this.fail >= 3;
|
||||
},
|
||||
multipliers: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {_id: 1}});
|
||||
var multipliers = [
|
||||
{name: "Acid", value: char.attributeValue("acidMultiplier", 1)},
|
||||
{name: "Bludgeoning", value: char.attributeValue("bludgeoningMultiplier", 1)},
|
||||
{name: "Cold", value: char.attributeValue("coldMultiplier", 1)},
|
||||
{name: "Fire", value: char.attributeValue("fireMultiplier", 1)},
|
||||
{name: "Force", value: char.attributeValue("forceMultiplier", 1)},
|
||||
{name: "Lightning", value: char.attributeValue("lightningMultiplier", 1)},
|
||||
{name: "Necrotic", value: char.attributeValue("necroticMultiplier", 1)},
|
||||
{name: "Piercing", value: char.attributeValue("piercingMultiplier", 1)},
|
||||
{name: "Poison", value: char.attributeValue("poisonMultiplier", 1)},
|
||||
{name: "Psychic", value: char.attributeValue("psychicMultiplier", 1)},
|
||||
{name: "Radiant", value: char.attributeValue("radiantMultiplier", 1)},
|
||||
{name: "Slashing", value: char.attributeValue("slashingMultiplier", 1)},
|
||||
{name: "Thunder", value: char.attributeValue("thunderMultiplier", 1)},
|
||||
{name: "Acid", value: Characters.calculate.attributeValue(this._id, "acidMultiplier")},
|
||||
{name: "Bludgeoning", value: Characters.calculate.attributeValue(this._id, "bludgeoningMultiplier")},
|
||||
{name: "Cold", value: Characters.calculate.attributeValue(this._id, "coldMultiplier")},
|
||||
{name: "Fire", value: Characters.calculate.attributeValue(this._id, "fireMultiplier")},
|
||||
{name: "Force", value: Characters.calculate.attributeValue(this._id, "forceMultiplier")},
|
||||
{name: "Lightning", value: Characters.calculate.attributeValue(this._id, "lightningMultiplier")},
|
||||
{name: "Necrotic", value: Characters.calculate.attributeValue(this._id, "necroticMultiplier")},
|
||||
{name: "Piercing", value: Characters.calculate.attributeValue(this._id, "piercingMultiplier")},
|
||||
{name: "Poison", value: Characters.calculate.attributeValue(this._id, "poisonMultiplier")},
|
||||
{name: "Psychic", value: Characters.calculate.attributeValue(this._id, "psychicMultiplier")},
|
||||
{name: "Radiant", value: Characters.calculate.attributeValue(this._id, "radiantMultiplier")},
|
||||
{name: "Slashing", value: Characters.calculate.attributeValue(this._id, "slashingMultiplier")},
|
||||
{name: "Thunder", value: Characters.calculate.attributeValue(this._id, "thunderMultiplier")},
|
||||
];
|
||||
multipliers = _.groupBy(multipliers, "value");
|
||||
return {
|
||||
@@ -55,7 +54,8 @@ Template.healthCard.helpers({
|
||||
Template.healthCard.events({
|
||||
"change #hitPointSlider": function(event){
|
||||
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}});
|
||||
//reset the death saves if we are gaining HP
|
||||
if (value > 0)
|
||||
|
||||
@@ -1,23 +1,32 @@
|
||||
<template name="hitDice">
|
||||
{{#if ../attributeBase name}}
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero name ../_id}} layout horizontal>
|
||||
<div class="containerLeft green" layout horizontal hero-id="toolbar" {{detailHero name ../_id}}>
|
||||
<div class="resourceButtons">
|
||||
<paper-icon-button class="resourceUp" icon="arrow-drop-up" disabled={{cantIncrement}}></paper-icon-button>
|
||||
<paper-icon-button class="resourceDown" icon="arrow-drop-down" disabled={{cantDecrement}}></paper-icon-button>
|
||||
{{#if characterCalculate "attributeBase" ../_id name}}
|
||||
<paper-shadow class="card hit-dice" hero-id="main"
|
||||
{{detailHero name ../_id}}
|
||||
layout horizontal>
|
||||
<div class="left green display1 white-text"
|
||||
hero-id="toolbar" {{detailHero name ../_id}}
|
||||
layout horizontal>
|
||||
<div>
|
||||
<paper-icon-button class="resourceUp"
|
||||
icon="arrow-drop-up"
|
||||
disabled={{cantIncrement}}>
|
||||
</paper-icon-button>
|
||||
<paper-icon-button class="resourceDown"
|
||||
icon="arrow-drop-down"
|
||||
disabled={{cantDecrement}}>
|
||||
</paper-icon-button>
|
||||
</div>
|
||||
<div class="resourceValue" layout vertical center>
|
||||
<div>
|
||||
{{../attributeValue name}}
|
||||
{{characterCalculate "attributeValue" ../_id name}}
|
||||
</div>
|
||||
<div class="title white-text">
|
||||
d{{diceNum}} {{../abilityMod "constitution"}}
|
||||
d{{diceNum}} {{characterCalculate "abilityMod" ../_id "constitution"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerRight clickable" flex relative horizontal layout center>
|
||||
<div class="right clickable" flex relative horizontal layout center>
|
||||
Hit Dice
|
||||
<paper-ripple fit></paper-ripple>
|
||||
</div>
|
||||
</paper-shadow>
|
||||
{{/if}}
|
||||
|
||||
@@ -1,36 +1,44 @@
|
||||
Template.hitDice.helpers({
|
||||
cantIncrement: function(){
|
||||
var valueSmallerThanBase = this.char.attributeValue(this.name) <
|
||||
this.char.attributeBase(this.name);
|
||||
return !valueSmallerThanBase;
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||
return value >= base;
|
||||
},
|
||||
cantDecrement: function(){
|
||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
||||
return !valuePositive;
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
return value <= 0;
|
||||
},
|
||||
});
|
||||
|
||||
Template.hitDice.events({
|
||||
"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: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .resourceDown": function(event){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
if (value > 0){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .containerRight": function() {
|
||||
"tap .right": function() {
|
||||
var charId = Template.parentData()._id;
|
||||
var title = "d" + this.diceNum + " Hit Dice";
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: title, statName: this.name, charId: charId},
|
||||
data: {
|
||||
name: title,
|
||||
statName: this.name,
|
||||
charId: charId,
|
||||
color: "green",
|
||||
},
|
||||
heroId: charId + this.name,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- needs name, char, and skillName -->
|
||||
<!-- needs name, charId, and skillName -->
|
||||
<template name="skillDialog">
|
||||
{{#baseDialog title=name class=colorClass hideEdit=true}}
|
||||
{{#baseDialog title=name class=color hideEdit=true}}
|
||||
{{> skillDialogView}}
|
||||
{{/baseDialog}}
|
||||
</template>
|
||||
@@ -8,7 +8,7 @@
|
||||
<template name="skillDialogView">
|
||||
<div layout vertical center>
|
||||
<div class="display2">
|
||||
{{char.skillMod skillName}}
|
||||
{{characterCalculate "skillMod" charId skillName}}
|
||||
</div>
|
||||
<div class="subhead">
|
||||
<core-icon icon="{{profIcon}}" class="black54"></core-icon>
|
||||
@@ -25,9 +25,9 @@
|
||||
<table class="summaryTable">
|
||||
<tr>
|
||||
<td>{{abilityName}}</td>
|
||||
<td>{{char.abilityMod ability}}</td>
|
||||
<td>{{characterCalculate "abilityMod" charId ability}}</td>
|
||||
</tr>
|
||||
{{#if char.proficiency skillName}}
|
||||
{{#if characterCalculate "proficiency" charId skillName}}
|
||||
<tr>
|
||||
<td>{{proficiencyValue}}</td>
|
||||
<td>{{signedString profBonus}}</td>
|
||||
@@ -59,7 +59,7 @@
|
||||
{{/each}}
|
||||
<tr class="body2">
|
||||
<td>Total</td>
|
||||
<td>{{char.skillMod skillName}}</td>
|
||||
<td>{{characterCalculate "skillMod" charId skillName}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -93,14 +93,20 @@ var abilities = {
|
||||
charisma: {name: "Charisma"},
|
||||
};
|
||||
|
||||
Template.skillDialog.helpers({
|
||||
color: function(){
|
||||
if (this.color) return this.color + " white-text";
|
||||
var char = Characters.findOne(this.charId, {fields: {color: 1}});
|
||||
if (char) return getColorClass(char.color);
|
||||
},
|
||||
});
|
||||
|
||||
Template.skillDialogView.helpers({
|
||||
or: function(a, b, c){
|
||||
return a || b || c;
|
||||
},
|
||||
profIcon: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
var prof = char.proficiency(this.skillName);
|
||||
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if (prof === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
@@ -115,13 +121,13 @@ Template.skillDialogView.helpers({
|
||||
profBonus: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
return char.proficiency(this.skillName) *
|
||||
char.attributeValue("proficiencyBonus");
|
||||
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||
var proficiencyBonus =
|
||||
Characters.calculate.attributeValue(this.charId, "proficiencyBonus");
|
||||
return prof * proficiencyBonus;
|
||||
},
|
||||
proficiencyValue: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
var prof = char.proficiency(this.skillName);
|
||||
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||
if (prof == 0.5) return "Half Proficiency";
|
||||
if (prof == 1) return "Proficient";
|
||||
if (prof == 2) return "Double Proficiency";
|
||||
@@ -132,6 +138,7 @@ Template.skillDialogView.helpers({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "add",
|
||||
enabled: true,
|
||||
});
|
||||
},
|
||||
mulEffects: function(){
|
||||
@@ -139,6 +146,7 @@ Template.skillDialogView.helpers({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "mul",
|
||||
enabled: true,
|
||||
});
|
||||
},
|
||||
minEffects: function(){
|
||||
@@ -146,6 +154,7 @@ Template.skillDialogView.helpers({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "min",
|
||||
enabled: true,
|
||||
});
|
||||
},
|
||||
maxEffects: function(){
|
||||
@@ -153,6 +162,7 @@ Template.skillDialogView.helpers({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "max",
|
||||
enabled: true,
|
||||
});
|
||||
},
|
||||
advEffects: function(){
|
||||
@@ -160,6 +170,7 @@ Template.skillDialogView.helpers({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "advantage",
|
||||
enabled: true,
|
||||
});
|
||||
},
|
||||
dadvEffects: function(){
|
||||
@@ -167,6 +178,7 @@ Template.skillDialogView.helpers({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "disadvantage",
|
||||
enabled: true,
|
||||
});
|
||||
},
|
||||
conditionalEffects: function(){
|
||||
@@ -174,6 +186,7 @@ Template.skillDialogView.helpers({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "conditional",
|
||||
enabled: true,
|
||||
});
|
||||
},
|
||||
ability: function(){
|
||||
@@ -184,20 +197,21 @@ Template.skillDialogView.helpers({
|
||||
return skill.ability;
|
||||
},
|
||||
abilityName: function(){
|
||||
var opts = {fields: {}};
|
||||
opts.fields[this.skillName] = 1;
|
||||
var char = Characters.findOne(this.charId, opts);
|
||||
if (!char) return;
|
||||
var skill = char[this.skillName];
|
||||
var skill = Characters.calculate.getField(this.charId, this.skillName);
|
||||
if (!skill) return;
|
||||
var ability = skill.ability;
|
||||
return abilities[ability] && abilities[ability].name;
|
||||
},
|
||||
char: function(){
|
||||
return Characters.findOne(this.charId, {fields:{_id: 1}});
|
||||
},
|
||||
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;
|
||||
},
|
||||
operationName: function(){
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
.skillRow {
|
||||
height: 32px;
|
||||
margin: 0 -16px 0 -16px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.skillRow core-icon {
|
||||
color: rgba(0,0,0,0.54);
|
||||
}
|
||||
|
||||
.skillMod {
|
||||
width: 42px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.skillName, .skillMod{
|
||||
|
||||
}
|
||||
|
||||
.fail.skillMod {
|
||||
color: #D50000;
|
||||
}
|
||||
|
||||
.advantage{
|
||||
background-image: url(/png/advantage/greenUp.png);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.disadvantage{
|
||||
background-image: url(/png/advantage/redDown.png);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.hasConditionals::after{
|
||||
content: "*";
|
||||
}
|
||||
@@ -1,16 +1,26 @@
|
||||
<template name="skillRow">
|
||||
<paper-item class="skillRow" layout horizontal hero-id="main" {{detailHero skill ../_id}}>
|
||||
<core-icon icon="{{profIcon}}"></core-icon>
|
||||
{{#if failSkill}}
|
||||
<div class="fail skillMod">fail</div>
|
||||
{{else}}
|
||||
<div class="{{advantage}} skillMod">{{../skillMod skill}}</div>
|
||||
{{/if}}
|
||||
<div class="{{#if conditionalCount}}hasConditionals{{/if}} skillName">
|
||||
{{name}}
|
||||
{{#if showPassive}}
|
||||
({{../passiveSkill skill}})
|
||||
<div class="item-slot">
|
||||
<div class="skill-row item small"
|
||||
hero-id="main"
|
||||
{{detailHero skill ../_id}}
|
||||
layout horizontal center>
|
||||
<core-icon icon="{{profIcon}}"></core-icon>
|
||||
{{#if failSkill}}
|
||||
<div class="fail skill-mod">fail</div>
|
||||
{{else}}
|
||||
<div class="{{advantage}} skill-mod">
|
||||
{{skillMod}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div flex>
|
||||
{{name}}
|
||||
{{#if conditionalCount}}
|
||||
*
|
||||
{{/if}}
|
||||
{{#if showPassive}}
|
||||
({{characterCalculate "passiveSkill" ../_id skill}})
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</paper-item>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,13 +1,21 @@
|
||||
Template.skillRow.helpers({
|
||||
skillMod: function() {
|
||||
return signedString(
|
||||
Characters.calculate.skillMod(
|
||||
Template.parentData()._id, this.skill
|
||||
)
|
||||
);
|
||||
},
|
||||
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 === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
return "radio-button-off";
|
||||
},
|
||||
failSkill: function(){
|
||||
var charId = Template.parentData(1)._id;
|
||||
var charId = Template.parentData()._id;
|
||||
return Effects.find({
|
||||
charId: charId,
|
||||
stat: this.skill,
|
||||
@@ -16,12 +24,13 @@ Template.skillRow.helpers({
|
||||
}).count();
|
||||
},
|
||||
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 "disadvantage";
|
||||
},
|
||||
conditionalCount: function(){
|
||||
var charId = Template.parentData(1)._id;
|
||||
var charId = Template.parentData()._id;
|
||||
return Effects.find({
|
||||
charId: charId,
|
||||
stat: this.skill,
|
||||
|
||||
21
rpg-docs/client/views/character/stats/skillRow/skillRow.scss
Normal file
21
rpg-docs/client/views/character/stats/skillRow/skillRow.scss
Normal file
@@ -0,0 +1,21 @@
|
||||
.skill-row {
|
||||
.skill-mod{
|
||||
width: 45px;
|
||||
text-align: center;
|
||||
&.fail {
|
||||
color: #D50000;
|
||||
}
|
||||
&.advantage{
|
||||
background-image: url(/png/advantage/greenUp.png);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
&.disadvantage{
|
||||
background-image: url(/png/advantage/redDown.png);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
<template name="stats">
|
||||
<div class="scroll-y" fit>
|
||||
<div class="resourceCards" layout horizontal wrap>
|
||||
<div style="padding: 8px 8px 0 8px">
|
||||
{{> healthCard}}
|
||||
</div>
|
||||
<div id="stats" class="containers" >
|
||||
<div class="column-container thin-columns" >
|
||||
<!--Ability Scores-->
|
||||
{{> abilityMiniCard ability="strength" title="Strength" color="red"}}
|
||||
{{> abilityMiniCard ability="dexterity" title="Dexterity" color="indigo"}}
|
||||
@@ -27,11 +27,11 @@
|
||||
{{>hitDice name="d10HitDice" diceNum="10" char=this}}
|
||||
{{>hitDice name="d12HitDice" diceNum="12" char=this}}
|
||||
<!--Saving Throws-->
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
|
||||
<div class="containerTop whiteTop" layout horizontal center>
|
||||
<div class="containerName subhead" hero-id="title" flex>Saving Throws</div>
|
||||
<paper-shadow class="card">
|
||||
<div class="top white subhead">
|
||||
Saving Throws
|
||||
</div>
|
||||
<div flex class="containerMain">
|
||||
<div flex class="bottom list">
|
||||
{{> skillRow name="Strength" skill="strengthSave"}}
|
||||
{{> skillRow name="Dexterity" skill="dexteritySave"}}
|
||||
{{> skillRow name="Constitution" skill="constitutionSave"}}
|
||||
@@ -41,11 +41,11 @@
|
||||
</div>
|
||||
</paper-shadow>
|
||||
<!--Skills-->
|
||||
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
|
||||
<div class="containerTop whiteTop" layout horizontal center>
|
||||
<div class="containerName subhead" hero-id="title" flex>Skills</div>
|
||||
<paper-shadow class="card">
|
||||
<div class="top white subhead">
|
||||
Skills
|
||||
</div>
|
||||
<div flex class="containerMain">
|
||||
<div flex class="bottom list">
|
||||
{{> skillRow name="Acrobatics" skill="acrobatics"}}
|
||||
{{> skillRow name="Animal Handling" skill="animalHandling"}}
|
||||
{{> skillRow name="Arcana" skill="arcana"}}
|
||||
@@ -71,18 +71,17 @@
|
||||
</template>
|
||||
|
||||
<template name="statCard">
|
||||
<paper-shadow class="card container statCard" hero-id="main" {{detailHero stat ../_id}} layout horizontal>
|
||||
<div class="containerLeft {{color}}"
|
||||
<paper-shadow class="card statCard clickable" hero-id="main" {{detailHero stat ../_id}} layout horizontal>
|
||||
<div class="left display1 white-text {{color}}"
|
||||
hero-id="toolbar" {{detailHero stat ../_id}}>
|
||||
{{#if isSkill}}
|
||||
{{../skillMod stat}}
|
||||
{{prefix}}{{skillMod}}
|
||||
{{else}}
|
||||
{{prefix}}{{../attributeValue stat}}
|
||||
{{prefix}}{{characterCalculate "attributeValue" ../_id stat}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="containerRight" flex horizontal layout center>
|
||||
<div class="right subhead" flex horizontal layout center>
|
||||
{{name}}
|
||||
</div>
|
||||
<paper-ripple fit></paper-ripple>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
|
||||
@@ -4,43 +4,75 @@ Template.stats.events({
|
||||
if (this.isSkill){
|
||||
GlobalUI.setDetail({
|
||||
template: "skillDialog",
|
||||
data: {name: this.name, skillName: this.stat, charId: charId},
|
||||
data: {
|
||||
name: this.name,
|
||||
skillName: this.stat,
|
||||
charId: charId,
|
||||
color: this.color,
|
||||
},
|
||||
heroId: charId + this.stat,
|
||||
});
|
||||
} else {
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: this.name, statName: this.stat, charId: charId},
|
||||
data: {
|
||||
name: this.name,
|
||||
statName: this.stat,
|
||||
charId: charId,
|
||||
color: this.color,
|
||||
},
|
||||
heroId: charId + this.stat,
|
||||
});
|
||||
}
|
||||
},
|
||||
"tap .abilityMiniCard": function(event, instance){
|
||||
var charId = Template.parentData()._id;
|
||||
var template = "attributeDialog";
|
||||
if (this.ability === "strength") template = "strengthDialog";
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: this.title, statName: this.ability, charId: charId},
|
||||
template: template,
|
||||
data: {
|
||||
name: this.title,
|
||||
statName: this.ability,
|
||||
charId: charId,
|
||||
color: this.color,
|
||||
},
|
||||
heroId: charId + this.ability,
|
||||
});
|
||||
},
|
||||
"tap .skillRow": function(event, instance){
|
||||
"tap .skill-row": function(event, instance){
|
||||
var skill = this.skill;
|
||||
var charId = instance.data._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "skillDialog",
|
||||
data: {name: this.name, skillName: skill, charId: charId},
|
||||
heroId: charId + skill,
|
||||
});
|
||||
template: "skillDialog",
|
||||
data: {
|
||||
name: this.name,
|
||||
skillName: skill,
|
||||
charId: charId,
|
||||
},
|
||||
heroId: charId + skill,
|
||||
});
|
||||
},
|
||||
"tap .hitPointTitle": function(event, instance) {
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: "Hit Points", statName: "hitPoints", charId: this._id},
|
||||
data: {
|
||||
name: "Hit Points",
|
||||
statName: "hitPoints",
|
||||
charId: this._id,
|
||||
color: "green",
|
||||
},
|
||||
heroId: this._id + "hitPoints",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
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">
|
||||
<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>
|
||||
<div flex>
|
||||
Characters
|
||||
|
||||
@@ -12,4 +12,11 @@
|
||||
height: 8px;
|
||||
margin-right: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.singleLineItem div {
|
||||
text-overflow: ellipsis;
|
||||
/* Required for text-overflow to do anything */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -21,8 +21,10 @@ Template.characterSideList.helpers({
|
||||
Template.characterSideList.events({
|
||||
"tap .singleLineItem": function(event, instance) {
|
||||
Router.go("characterSheet", {_id: this._id});
|
||||
$("core-drawer-panel").get(0).closeDrawer();
|
||||
},
|
||||
"tap core-item": function() {
|
||||
Router.go("characterList");
|
||||
$("core-drawer-panel").get(0).closeDrawer();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
</div>
|
||||
<paper-button id="cancelButton" affirmative>Cancel</paper-button>
|
||||
<paper-button id="sendButton" affirmative>Send </paper-button>
|
||||
<paper-button id="cancelButton"
|
||||
affirmative>
|
||||
Cancel
|
||||
</paper-button>
|
||||
<paper-button id="sendButton"
|
||||
affirmative
|
||||
disabled={{invalid}}>
|
||||
Send
|
||||
</paper-button>
|
||||
</template>
|
||||
@@ -1,4 +1,23 @@
|
||||
Template.feedback.onCreated(function() {
|
||||
this.title = new ReactiveVar("");
|
||||
this.description = new ReactiveVar("");
|
||||
});
|
||||
|
||||
Template.feedback.helpers({
|
||||
invalid: function() {
|
||||
var inst = Template.instance();
|
||||
return !inst.title.get() ||
|
||||
!inst.description.get();
|
||||
}
|
||||
});
|
||||
|
||||
Template.feedback.events({
|
||||
"input #feedbackTitle": function(event, instance) {
|
||||
instance.title.set(instance.find("#feedbackTitle").value);
|
||||
},
|
||||
"input #feedbackDescription": function(event, instance) {
|
||||
instance.description.set(instance.find("#feedbackDescription").value);
|
||||
},
|
||||
"tap #sendButton": function(event, instance) {
|
||||
var report = {};
|
||||
report.title = instance.find("#feedbackTitle").value;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user