Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54f055d3ef | ||
|
|
2bacb296ba | ||
|
|
8b061f7aa9 | ||
|
|
6a84c83644 | ||
|
|
3227cd0934 | ||
|
|
089feae26f | ||
|
|
99c72d1e10 | ||
|
|
1e67afbe6f | ||
|
|
1cfec1ca45 |
@@ -48,3 +48,4 @@ es5-shim@4.6.15
|
|||||||
differential:vulcanize
|
differential:vulcanize
|
||||||
reactive-dict
|
reactive-dict
|
||||||
percolate:synced-cron
|
percolate:synced-cron
|
||||||
|
ongoworks:speakingurl
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ npm-mongo@2.2.16_1
|
|||||||
oauth@1.1.12
|
oauth@1.1.12
|
||||||
oauth2@1.1.11
|
oauth2@1.1.11
|
||||||
observe-sequence@1.0.14
|
observe-sequence@1.0.14
|
||||||
|
ongoworks:speakingurl@9.0.0
|
||||||
ordered-dict@1.0.9
|
ordered-dict@1.0.9
|
||||||
percolate:migrations@0.9.8
|
percolate:migrations@0.9.8
|
||||||
percolate:synced-cron@1.3.2
|
percolate:synced-cron@1.3.2
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ Schemas.Action = new SimpleSchema({
|
|||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
|
optional: true,
|
||||||
trim: false,
|
trim: false,
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
type: String,
|
type: String,
|
||||||
|
optional: true,
|
||||||
trim: false,
|
trim: false,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Schemas.Attack = new SimpleSchema({
|
|||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
defaultValue: "New Attack",
|
defaultValue: "New Attack",
|
||||||
|
optional: true,
|
||||||
trim: false,
|
trim: false,
|
||||||
},
|
},
|
||||||
details: {
|
details: {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Schemas.Buff = new SimpleSchema({
|
|||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
|
optional: true,
|
||||||
trim: false,
|
trim: false,
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Characters = new Mongo.Collection("characters");
|
|||||||
Schemas.Character = new SimpleSchema({
|
Schemas.Character = new SimpleSchema({
|
||||||
//strings
|
//strings
|
||||||
name: {type: String, defaultValue: "", trim: false, optional: true},
|
name: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
|
urlName: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
alignment: {type: String, defaultValue: "", trim: false, optional: true},
|
alignment: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
gender: {type: String, defaultValue: "", trim: false, optional: true},
|
gender: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
race: {type: String, defaultValue: "", trim: false, optional: true},
|
race: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
@@ -257,7 +258,10 @@ var attributeBase = preventLoop(function(charId, statName){
|
|||||||
var result = (base + add) * mul;
|
var result = (base + add) * mul;
|
||||||
if (result < min) result = min;
|
if (result < min) result = min;
|
||||||
if (result > max) result = max;
|
if (result > max) result = max;
|
||||||
|
// Don't round carry multiplier
|
||||||
|
if (statName === "carryMultiplier"){
|
||||||
|
return result;
|
||||||
|
}
|
||||||
return Math.floor(result);
|
return Math.floor(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -537,6 +541,12 @@ if (Meteor.isServer){
|
|||||||
Items .remove({charId: character._id});
|
Items .remove({charId: character._id});
|
||||||
Containers .remove({charId: character._id});
|
Containers .remove({charId: character._id});
|
||||||
});
|
});
|
||||||
|
Characters.after.update(function(userId, doc, fieldNames, modifier, options) {
|
||||||
|
if (_.contains(fieldNames, "name")){
|
||||||
|
var urlName = getSlug(doc.name, {maintainCase: true});
|
||||||
|
Characters.update(doc._id, {$set: {urlName}});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Characters.allow({
|
Characters.allow({
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Classes = new Mongo.Collection("classes");
|
|||||||
|
|
||||||
Schemas.Class = new SimpleSchema({
|
Schemas.Class = new SimpleSchema({
|
||||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||||
name: {type: String, trim: false},
|
name: {type: String, optional: true, trim: false},
|
||||||
level: {type: Number},
|
level: {type: Number},
|
||||||
createdAt: {
|
createdAt: {
|
||||||
type: Date,
|
type: Date,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Experiences = new Mongo.Collection("experience");
|
|||||||
|
|
||||||
Schemas.Experience = new SimpleSchema({
|
Schemas.Experience = new SimpleSchema({
|
||||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||||
name: {type: String, defaultValue: "New Experience", trim: false},
|
name: {type: String, optional: true, trim: false, defaultValue: "New Experience"},
|
||||||
description: {type: String, optional: true, trim: false},
|
description: {type: String, optional: true, trim: false},
|
||||||
value: {type: Number, defaultValue: 0},
|
value: {type: Number, defaultValue: 0},
|
||||||
dateAdded: {
|
dateAdded: {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Features = new Mongo.Collection("features");
|
|||||||
|
|
||||||
Schemas.Feature = new SimpleSchema({
|
Schemas.Feature = new SimpleSchema({
|
||||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||||
name: {type: String, trim: false},
|
name: {type: String, optional: true, trim: false},
|
||||||
description: {type: String, optional: true, trim: false},
|
description: {type: String, optional: true, trim: false},
|
||||||
uses: {type: String, optional: true, trim: false},
|
uses: {type: String, optional: true, trim: false},
|
||||||
used: {type: Number, defaultValue: 0},
|
used: {type: Number, defaultValue: 0},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Notes = new Mongo.Collection("notes");
|
|||||||
|
|
||||||
Schemas.Note = new SimpleSchema({
|
Schemas.Note = new SimpleSchema({
|
||||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||||
name: {type: String, trim: false},
|
name: {type: String, optional: true, trim: false},
|
||||||
description: {type: String, optional: true, trim: false},
|
description: {type: String, optional: true, trim: false},
|
||||||
color: {
|
color: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ SpellLists = new Mongo.Collection("spellLists");
|
|||||||
|
|
||||||
Schemas.SpellLists = new SimpleSchema({
|
Schemas.SpellLists = new SimpleSchema({
|
||||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||||
name: {type: String, trim: false},
|
name: {type: String, optional: true, trim: false},
|
||||||
description: {type: String, optional: true, trim: false},
|
description: {type: String, optional: true, trim: false},
|
||||||
saveDC: {type: String, optional: true, trim: false},
|
saveDC: {type: String, optional: true, trim: false},
|
||||||
attackBonus: {type: String, optional: true, trim: false},
|
attackBonus: {type: String, optional: true, trim: false},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Schemas.Spell = new SimpleSchema({
|
|||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
|
optional: true,
|
||||||
trim: false,
|
trim: false,
|
||||||
defaultValue: "New Spell",
|
defaultValue: "New Spell",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
Containers = new Mongo.Collection("containers");
|
Containers = new Mongo.Collection("containers");
|
||||||
|
|
||||||
Schemas.Container = new SimpleSchema({
|
Schemas.Container = new SimpleSchema({
|
||||||
name: {type: String, trim: false},
|
name: {type: String, optional: true, trim: false},
|
||||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||||
isCarried: {type: Boolean},
|
isCarried: {type: Boolean},
|
||||||
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Items = new Mongo.Collection("items");
|
Items = new Mongo.Collection("items");
|
||||||
|
|
||||||
Schemas.Item = new SimpleSchema({
|
Schemas.Item = new SimpleSchema({
|
||||||
name: {type: String, defaultValue: "New Item", trim: false},
|
name: {type: String, optional: true, trim: false, defaultValue: "New Item"},
|
||||||
plural: {type: String, optional: true, trim: false},
|
plural: {type: String, optional: true, trim: false},
|
||||||
description:{type: String, optional: true, trim: false},
|
description:{type: String, optional: true, trim: false},
|
||||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, //id of owner
|
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, //id of owner
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Router.map(function() {
|
|||||||
this.route("characterList", {
|
this.route("characterList", {
|
||||||
path: "/characterList",
|
path: "/characterList",
|
||||||
waitOn: function(){
|
waitOn: function(){
|
||||||
return subsManager.subscribe("characterList", Meteor.userId());
|
return subsManager.subscribe("characterList");
|
||||||
},
|
},
|
||||||
onAfterAction: function() {
|
onAfterAction: function() {
|
||||||
document.title = appName + " - Characters";
|
document.title = appName + " - Characters";
|
||||||
@@ -32,11 +32,27 @@ Router.map(function() {
|
|||||||
fastRender: true,
|
fastRender: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route("characterSheet", {
|
this.route("characterSheetNaked", {
|
||||||
path: "/character/:_id",
|
path: "/character/:_id/",
|
||||||
waitOn: function(){
|
waitOn: function(){
|
||||||
return [
|
return [
|
||||||
subsManager.subscribe("singleCharacter", this.params._id, Meteor.userId()),
|
subsManager.subscribe("singleCharacter", this.params._id),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
action: function(){
|
||||||
|
var _id = this.params._id
|
||||||
|
var character = Characters.findOne(_id);
|
||||||
|
var urlName = character && character.urlName;
|
||||||
|
var path = `\/character\/${_id}\/${urlName}`;
|
||||||
|
Router.go(path,{},{replaceState:true});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("characterSheet", {
|
||||||
|
path: "/character/:_id/:urlName",
|
||||||
|
waitOn: function(){
|
||||||
|
return [
|
||||||
|
subsManager.subscribe("singleCharacter", this.params._id),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
data: function() {
|
data: function() {
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ Template.registerHelper("evaluateString", function(charId, string) {
|
|||||||
return evaluateString(charId, string);
|
return evaluateString(charId, string);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Template.registerHelper("evaluateSpellString", function(charId, spellListId, string) {
|
||||||
|
return evaluateSpellString(charId, spellListId, string);
|
||||||
|
});
|
||||||
|
|
||||||
Template.registerHelper("evaluateShortString", function(charId, string) {
|
Template.registerHelper("evaluateShortString", function(charId, string) {
|
||||||
if (_.isString(string)){
|
if (_.isString(string)){
|
||||||
return evaluateString(
|
return evaluateString(
|
||||||
|
|||||||
28
rpg-docs/client/lib/requestAnimationFramePolyfill.js
Normal file
28
rpg-docs/client/lib/requestAnimationFramePolyfill.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
||||||
|
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
|
||||||
|
|
||||||
|
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
|
||||||
|
|
||||||
|
// MIT license
|
||||||
|
var lastTime = 0;
|
||||||
|
var vendors = ["ms", "moz", "webkit", "o"];
|
||||||
|
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||||
|
window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"];
|
||||||
|
window.cancelAnimationFrame = window[vendors[x] + "CancelAnimationFrame"] ||
|
||||||
|
window[vendors[x] + "CancelRequestAnimationFrame"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.requestAnimationFrame)
|
||||||
|
window.requestAnimationFrame = function(callback, element) {
|
||||||
|
var currTime = new Date().getTime();
|
||||||
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||||
|
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
|
||||||
|
timeToCall);
|
||||||
|
lastTime = currTime + timeToCall;
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.cancelAnimationFrame)
|
||||||
|
window.cancelAnimationFrame = function(id) {
|
||||||
|
clearTimeout(id);
|
||||||
|
};
|
||||||
@@ -20,26 +20,28 @@
|
|||||||
<div class="effectEdit layout horizontal flex">
|
<div class="effectEdit layout horizontal flex">
|
||||||
<dicecloud-selector class="statMenu flex" selected={{stat}} selectable="paper-item" style="height: 100%; overflow-y: auto;">
|
<dicecloud-selector class="statMenu flex" selected={{stat}} selectable="paper-item" style="height: 100%; overflow-y: auto;">
|
||||||
{{#each statGroups}}
|
{{#each statGroups}}
|
||||||
<div style="font-weight: bold; margin-top: 16px; padding-left: 8px;">
|
<div class="statGroupTitle clickable" style="font-weight: bold; margin-top: 16px; padding-left: 8px;">
|
||||||
{{this}}
|
{{this}}
|
||||||
</div>
|
</div>
|
||||||
{{#each stats}}
|
<iron-collapse opened={{isGroupSelected this ../stat}}>
|
||||||
<paper-item name={{stat}}>{{name}}</paper-item>
|
{{#each stats}}
|
||||||
{{/each}}
|
<paper-item name={{stat}} class="clickable">{{name}}</paper-item>
|
||||||
|
{{/each}}
|
||||||
|
</iron-collapse>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</dicecloud-selector>
|
</dicecloud-selector>
|
||||||
{{#if operations}}
|
{{#if operations}}
|
||||||
<dicecloud-selector class="operationMenu flex" selected={{operation}} style="height: 100%; overflow-y: auto;">
|
<dicecloud-selector class="operationMenu flex" selected={{operation}} style="height: 100%; overflow-y: auto;">
|
||||||
{{#each operations}}
|
{{#each operations}}
|
||||||
<paper-item name={{operation}}>{{name}}</paper-item>
|
<paper-item name={{operation}} class="clickable">{{name}}</paper-item>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</dicecloud-selector>
|
</dicecloud-selector>
|
||||||
{{else}} {{#if showMultiplierOperations}}
|
{{else}} {{#if showMultiplierOperations}}
|
||||||
<dicecloud-selector class="multiplierMenu flex"
|
<dicecloud-selector class="multiplierMenu flex"
|
||||||
selected={{value}}>
|
selected={{value}}>
|
||||||
<paper-item name="0.5">Resistance</paper-item>
|
<paper-item name="0.5" class="clickable">Resistance</paper-item>
|
||||||
<paper-item name="2">Vulnerability</paper-item>
|
<paper-item name="2" class="clickable">Vulnerability</paper-item>
|
||||||
<paper-item name="0">Immunity</paper-item>
|
<paper-item name="0" class="clickable">Immunity</paper-item>
|
||||||
</dicecloud-selector>
|
</dicecloud-selector>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="flex" style="height: 100%;"></div>
|
<div class="flex" style="height: 100%;"></div>
|
||||||
|
|||||||
@@ -149,47 +149,71 @@ Template.effectEdit.helpers({
|
|||||||
effectValue: function(){
|
effectValue: function(){
|
||||||
return this.calculation || this.value;
|
return this.calculation || this.value;
|
||||||
},
|
},
|
||||||
|
isGroupSelected: function(groupName, statName){
|
||||||
|
var stat = statsDict[statName]
|
||||||
|
return stat && (stat.group === groupName);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var setStat = function(statName, effectId){
|
||||||
|
var setter = {stat: statName};
|
||||||
|
var effect = Effects.findOne(this._id);
|
||||||
|
var group = statsDict[statName].group;
|
||||||
|
if (group === "Saving Throws" || group === "Skills"){
|
||||||
|
// Skills must have a valid skill operation
|
||||||
|
if (!_.contains(
|
||||||
|
_.map(skillOperations, ao => ao.operation),
|
||||||
|
effect.operation
|
||||||
|
)){
|
||||||
|
setter.operation = "add";
|
||||||
|
}
|
||||||
|
} else if (group !== "Weakness/Resistance"){
|
||||||
|
// Attributes must have a valid attribute operation
|
||||||
|
if (!_.contains(
|
||||||
|
_.map(attributeOperations, ao => ao.operation),
|
||||||
|
effect.operation
|
||||||
|
)){
|
||||||
|
setter.operation = "base";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Weakness/Resistance must have a mul operation and value
|
||||||
|
if (effect.operation !== "mul"){
|
||||||
|
setter.operation = "mul";
|
||||||
|
}
|
||||||
|
if (!_.contains([0, 0.5, 2], effect.value)){
|
||||||
|
setter.value = 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Effects.update(effectId, {$set: setter});
|
||||||
|
};
|
||||||
|
|
||||||
|
var scrollAnimationId;
|
||||||
|
var scrollElementToView = element => {
|
||||||
|
var scrollFunction = function(){
|
||||||
|
element.scrollIntoView();
|
||||||
|
scrollAnimationId = requestAnimationFrame(scrollFunction);
|
||||||
|
};
|
||||||
|
return scrollFunction;
|
||||||
|
}
|
||||||
|
|
||||||
Template.effectEdit.events({
|
Template.effectEdit.events({
|
||||||
"click #deleteButton": function(event, instance){
|
"click #deleteButton": function(event, instance){
|
||||||
Effects.softRemoveNode(instance.data.id);
|
Effects.softRemoveNode(instance.data.id);
|
||||||
GlobalUI.deletedToast(instance.data.id, "Effects", "Effect");
|
GlobalUI.deletedToast(instance.data.id, "Effects", "Effect");
|
||||||
popDialogStack();
|
popDialogStack();
|
||||||
},
|
},
|
||||||
|
"click .statGroupTitle": function(event, instance){
|
||||||
|
var groupName = this.toString();
|
||||||
|
var firstStat = statGroups[groupName][0].stat;
|
||||||
|
setStat(firstStat, instance.data.id);
|
||||||
|
scrollAnimationId = requestAnimationFrame(scrollElementToView(event.target));
|
||||||
|
_.delay(() => cancelAnimationFrame(scrollAnimationId), 300);
|
||||||
|
},
|
||||||
"iron-select .statMenu": function(event){
|
"iron-select .statMenu": function(event){
|
||||||
var detail = event.originalEvent.detail;
|
var detail = event.originalEvent.detail;
|
||||||
var statName = detail.item.getAttribute("name");
|
var statName = detail.item.getAttribute("name");
|
||||||
if (statName == this.stat) return;
|
if (statName == this.stat) return;
|
||||||
var setter = {stat: statName};
|
setStat(statName, this._id);
|
||||||
var group = Blaze.getData(detail.item).group;
|
|
||||||
var effect = Effects.findOne(this._id);
|
|
||||||
if (group === "Saving Throws" || group === "Skills"){
|
|
||||||
// Skills must have a valid skill operation
|
|
||||||
if (!_.contains(
|
|
||||||
_.map(skillOperations, ao => ao.operation),
|
|
||||||
effect.operation
|
|
||||||
)){
|
|
||||||
setter.operation = "add";
|
|
||||||
}
|
|
||||||
} else if (group !== "Weakness/Resistance"){
|
|
||||||
// Attributes must have a valid attribute operation
|
|
||||||
if (!_.contains(
|
|
||||||
_.map(attributeOperations, ao => ao.operation),
|
|
||||||
effect.operation
|
|
||||||
)){
|
|
||||||
setter.operation = "base";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Weakness/Resistance must have a mul operation and value
|
|
||||||
if (effect.operation !== "mul"){
|
|
||||||
setter.operation = "mul";
|
|
||||||
}
|
|
||||||
if (!_.contains([0, 0.5, 2], effect.value)){
|
|
||||||
setter.value = 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Effects.update(this._id, {$set: setter});
|
|
||||||
},
|
},
|
||||||
"iron-select .operationMenu": function(event){
|
"iron-select .operationMenu": function(event){
|
||||||
var detail = event.originalEvent.detail;
|
var detail = event.originalEvent.detail;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ Template.effectsEditList.events({
|
|||||||
template: "effectEdit",
|
template: "effectEdit",
|
||||||
data: {id: effectId},
|
data: {id: effectId},
|
||||||
element: event.currentTarget,
|
element: event.currentTarget,
|
||||||
returnElement: instance.find(`tr.effect[data-id='${effectId}']`),
|
returnElement: () => instance.find(`tr.effect[data-id='${effectId}']`),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
"tap .edit-effect": function(event, template){
|
"tap .edit-effect": function(event, template){
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
<div>{{#markdown}}{{evaluateSpellString charId parent.id description}}{{/markdown}}</div>
|
||||||
{{> attacksViewList charId=charId parentId=_id}}
|
{{> attacksViewList charId=charId parentId=_id}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,18 @@
|
|||||||
<td>Total</td>
|
<td>Total</td>
|
||||||
<td>{{characterCalculate "skillMod" charId skillName}}</td>
|
<td>{{characterCalculate "skillMod" charId skillName}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{{#each passiveEffects}}
|
||||||
|
<tr>
|
||||||
|
<td>{{sourceName}}</td>
|
||||||
|
<td>Passive Bonus: {{statValue}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
{{#if showPassiveTotal}}
|
||||||
|
<tr class="paper-font-body2">
|
||||||
|
<td>Passive Score</td>
|
||||||
|
<td>{{characterCalculate "passiveSkill" charId skillName}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/if}}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ Template.skillDialogView.helpers({
|
|||||||
var char = Characters.findOne(this.charId);
|
var char = Characters.findOne(this.charId);
|
||||||
if (!char) return;
|
if (!char) return;
|
||||||
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||||
var proficiencyBonus =
|
var proficiencyBonus =
|
||||||
Characters.calculate.attributeValue(this.charId, "proficiencyBonus");
|
Characters.calculate.attributeValue(this.charId, "proficiencyBonus");
|
||||||
return prof * proficiencyBonus;
|
return prof * proficiencyBonus;
|
||||||
},
|
},
|
||||||
@@ -189,6 +189,23 @@ Template.skillDialogView.helpers({
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
passiveEffects: function(){
|
||||||
|
return Effects.find({
|
||||||
|
charId: this.charId,
|
||||||
|
stat: this.skillName,
|
||||||
|
operation: "passiveAdd",
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showPassiveTotal: function(){
|
||||||
|
if (this.skillName === "perception") return true;
|
||||||
|
return Effects.find({
|
||||||
|
charId: this.charId,
|
||||||
|
stat: this.skillName,
|
||||||
|
operation: "passiveAdd",
|
||||||
|
enabled: true,
|
||||||
|
}).count();
|
||||||
|
},
|
||||||
ability: function(){
|
ability: function(){
|
||||||
var opts = {fields: {}};
|
var opts = {fields: {}};
|
||||||
opts.fields[this.skillName] = 1;
|
opts.fields[this.skillName] = 1;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
{{#if conditionalCount}}
|
{{#if conditionalCount}}
|
||||||
*
|
*
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if showPassive}}
|
{{#if isPassiveShown}}
|
||||||
({{characterCalculate "passiveSkill" ../_id skill}})
|
({{characterCalculate "passiveSkill" ../_id skill}})
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -38,4 +38,16 @@ Template.skillRow.helpers({
|
|||||||
operation: "conditional",
|
operation: "conditional",
|
||||||
}).count();
|
}).count();
|
||||||
},
|
},
|
||||||
|
isPassiveShown: function(){
|
||||||
|
if (this.showPassive === "forced") return true;
|
||||||
|
if (this.showPassive === "ifNeeded"){
|
||||||
|
var charId = Template.parentData()._id;
|
||||||
|
return Effects.find({
|
||||||
|
charId,
|
||||||
|
stat: this.skill,
|
||||||
|
operation: "passiveAdd",
|
||||||
|
enabled: true,
|
||||||
|
}).count();
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -49,24 +49,24 @@
|
|||||||
Skills
|
Skills
|
||||||
</div>
|
</div>
|
||||||
<div flex class="bottom list">
|
<div flex class="bottom list">
|
||||||
{{> skillRow name="Acrobatics" skill="acrobatics"}}
|
{{> skillRow name="Acrobatics" skill="acrobatics" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Animal Handling" skill="animalHandling"}}
|
{{> skillRow name="Animal Handling" skill="animalHandling" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Arcana" skill="arcana"}}
|
{{> skillRow name="Arcana" skill="arcana" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Athletics" skill="athletics"}}
|
{{> skillRow name="Athletics" skill="athletics" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Deception" skill="deception"}}
|
{{> skillRow name="Deception" skill="deception" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="History" skill="history"}}
|
{{> skillRow name="History" skill="history" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Insight" skill="insight"}}
|
{{> skillRow name="Insight" skill="insight" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Intimidation" skill="intimidation"}}
|
{{> skillRow name="Intimidation" skill="intimidation" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Investigation" skill="investigation"}}
|
{{> skillRow name="Investigation" skill="investigation" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Medicine" skill="medicine"}}
|
{{> skillRow name="Medicine" skill="medicine" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Nature" skill="nature"}}
|
{{> skillRow name="Nature" skill="nature" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Perception" skill="perception" showPassive="true"}}
|
{{> skillRow name="Perception" skill="perception" showPassive="forced"}}
|
||||||
{{> skillRow name="Performance" skill="performance"}}
|
{{> skillRow name="Performance" skill="performance" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Persuasion" skill="persuasion"}}
|
{{> skillRow name="Persuasion" skill="persuasion" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Religion" skill="religion"}}
|
{{> skillRow name="Religion" skill="religion" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Sleight of Hand" skill="sleightOfHand"}}
|
{{> skillRow name="Sleight of Hand" skill="sleightOfHand" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Stealth" skill="stealth"}}
|
{{> skillRow name="Stealth" skill="stealth" showPassive="ifNeeded"}}
|
||||||
{{> skillRow name="Survival" skill="survival"}}
|
{{> skillRow name="Survival" skill="survival" showPassive="ifNeeded"}}
|
||||||
</div>
|
</div>
|
||||||
</paper-material>
|
</paper-material>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{{#if characters.count}}
|
{{#if characters.count}}
|
||||||
<div class="character-list layout horizontal wrap">
|
<div class="character-list layout horizontal wrap">
|
||||||
{{# each characters}}
|
{{# each characters}}
|
||||||
<a class="character-card flex layout vertical end-justified" href="/character/{{_id}}">
|
<a class="character-card flex layout vertical end-justified" href="{{pathFor route="characterSheet" data=this}}">
|
||||||
<iron-image class="fit {{colorClass}}"
|
<iron-image class="fit {{colorClass}}"
|
||||||
sizing="cover" preload fade src={{picture}}>
|
sizing="cover" preload fade src={{picture}}>
|
||||||
</iron-image>
|
</iron-image>
|
||||||
|
|||||||
@@ -10,7 +10,15 @@ Template.characterList.helpers({
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fields: {name: 1, picture: 1, color: 1, race: 1, alignment: 1, gender: 1},
|
fields: {
|
||||||
|
name: 1,
|
||||||
|
urlName: 1,
|
||||||
|
picture: 1,
|
||||||
|
color: 1,
|
||||||
|
race: 1,
|
||||||
|
alignment: 1,
|
||||||
|
gender: 1,
|
||||||
|
},
|
||||||
sort: {name: 1},
|
sort: {name: 1},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Template.characterSideList.helpers({
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fields: {name: 1},
|
fields: {name: 1, urlName: 1},
|
||||||
sort: {name: 1},
|
sort: {name: 1},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
//evaluates a calculation string
|
//evaluates a calculation string
|
||||||
evaluate = function(charId, string){
|
evaluate = function(charId, string, opts){
|
||||||
|
var spellListId = opts && opts.spellListId;
|
||||||
if (!string) return string;
|
if (!string) return string;
|
||||||
string = string.replace(/\b[a-z]+\b/gi, function(sub){
|
string = string.replace(/\b[a-z,1-9]+\b/gi, function(sub){
|
||||||
//fields
|
//fields
|
||||||
if (Schemas.Character.schema(sub)){
|
if (Schemas.Character.schema(sub)){
|
||||||
return Characters.calculate.fieldValue(charId, sub);
|
return Characters.calculate.fieldValue(charId, sub);
|
||||||
@@ -43,6 +44,12 @@ evaluate = function(charId, string){
|
|||||||
if (sub.toUpperCase() === "LEVEL"){
|
if (sub.toUpperCase() === "LEVEL"){
|
||||||
return Characters.calculate.level(charId);
|
return Characters.calculate.level(charId);
|
||||||
}
|
}
|
||||||
|
if (spellListId && sub.toUpperCase() === "DC") {
|
||||||
|
var list = SpellLists.findOne(spellListId);
|
||||||
|
if (list && list.saveDC){
|
||||||
|
return evaluate(charId, list.saveDC);
|
||||||
|
}
|
||||||
|
}
|
||||||
return sub;
|
return sub;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
@@ -66,6 +73,17 @@ evaluateString = function(charId, string){
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
evaluateSpellString = function (charId, spellListId, string) {
|
||||||
|
//define brackets as curly brackets around anything that isn't a curly bracket
|
||||||
|
if (!string) return string;
|
||||||
|
var brackets = /\{[^\{\}]*\}/g;
|
||||||
|
var result = string.replace(brackets, function(exp){
|
||||||
|
exp = exp.replace(/(\{|\})/g, ""); //remove curly brackets
|
||||||
|
return evaluate(charId, exp, {spellListId});
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//returns the value of the effect if it exists,
|
//returns the value of the effect if it exists,
|
||||||
//otherwise returns the result of the calculation if it exists,
|
//otherwise returns the result of the calculation if it exists,
|
||||||
//otherwise returns 0
|
//otherwise returns 0
|
||||||
|
|||||||
@@ -249,7 +249,9 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
_updateItems: function() {
|
_updateItems: function() {
|
||||||
var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
|
var nodes = this.selectable
|
||||||
|
? Polymer.dom(this).querySelectorAll(this.selectable)
|
||||||
|
: Polymer.dom(this).queryDistributedElements('*');
|
||||||
nodes = Array.prototype.filter.call(nodes, this._bindFilterItem);
|
nodes = Array.prototype.filter.call(nodes, this._bindFilterItem);
|
||||||
this._setItems(nodes);
|
this._setItems(nodes);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ Migrations.add({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
var effect = Effects.findOne({
|
var effect = Effects.findOne({
|
||||||
charId: char._id, name: "Natural Carrying Capacity"
|
charId: char._id, name: "Natural Carrying Capacity",
|
||||||
});
|
});
|
||||||
if (effect) return;
|
if (effect) return;
|
||||||
Effects.insert({
|
Effects.insert({
|
||||||
@@ -141,7 +141,7 @@ Migrations.add({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
effect = Effects.findOne({
|
effect = Effects.findOne({
|
||||||
charId: char._id, name: "Natural Carrying Capacity"
|
charId: char._id, name: "Natural Carrying Capacity",
|
||||||
});
|
});
|
||||||
if (!effect) throw "Carry capacity effect should be set by now."
|
if (!effect) throw "Carry capacity effect should be set by now."
|
||||||
});
|
});
|
||||||
@@ -150,3 +150,19 @@ Migrations.add({
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Migrations.add({
|
||||||
|
version: 5,
|
||||||
|
name: "Gives all characters a URL name",
|
||||||
|
up: function() {
|
||||||
|
//update characters
|
||||||
|
Characters.find({}).forEach(function(char){
|
||||||
|
if (char.urlName) return;
|
||||||
|
var urlName = getSlug(char.name, {maintainCase: true});
|
||||||
|
Characters.update(char._id, {$set: {urlName}});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
down: function(){
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Meteor.publish("characterList", function(){
|
|||||||
{
|
{
|
||||||
fields: {
|
fields: {
|
||||||
name: 1,
|
name: 1,
|
||||||
|
urlName: 1,
|
||||||
race: 1,
|
race: 1,
|
||||||
alignment: 1,
|
alignment: 1,
|
||||||
gender: 1,
|
gender: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user