Compare commits

...

37 Commits
0.6.4 ... 0.7.0

Author SHA1 Message Date
Stefan Zermatten
b578dd5fb0 Merge branch 'feature-carry-capacity-modifier' 2015-09-03 14:09:51 +02:00
Stefan Zermatten
5d6f934d88 Bumped version 2015-09-03 14:09:23 +02:00
Stefan Zermatten
337f0bfa8a Made sure migration touches every character 2015-09-03 14:09:17 +02:00
Stefan Zermatten
c62784894b Made sure encumbered conditions respect carry capacity 2015-09-03 13:53:00 +02:00
Stefan Zermatten
75fff43d7d Gave an effect menu option for carry capacity 2015-09-03 13:52:40 +02:00
Stefan Zermatten
a9eeeac0df Fixed carry capacity bar 2015-09-03 13:52:22 +02:00
Stefan Zermatten
c8af0ff0a9 Fixed carry capacity table 2015-09-03 13:52:06 +02:00
Stefan Zermatten
9e200db7b9 Made carry capacity an attribute, migrations need testing 2015-08-31 15:51:52 +02:00
Stefan Zermatten
c08cf83096 Bumped version 2015-08-27 12:21:23 +02:00
Stefan Zermatten
d9368b06d0 Merge branch 'bugfix-0.6.8' 2015-08-27 12:07:42 +02:00
Stefan Zermatten
2703367681 Proficiencies now get disabled when their features are disabled 2015-08-27 12:05:56 +02:00
Stefan Zermatten
d419442549 Fixed share dialog not finding usernames or email addresses 2015-08-27 11:59:38 +02:00
Stefan Zermatten
99df01c950 Prevented negative temporary hitpoints being added 2015-08-27 11:43:34 +02:00
Stefan Zermatten
d76349b3bb Merge branch 'release-0.6.7a' 2015-07-29 09:57:06 +02:00
Stefan Zermatten
39c061f4e8 Fixed formatting of not found page, now has a toolbar and centered text 2015-07-29 09:55:22 +02:00
Stefan Zermatten
6d167ddb22 Fixed formatting of loading page, more padding 2015-07-29 09:55:01 +02:00
Stefan Zermatten
037acbd459 Added Starter Set Wizard to the front page 2015-07-29 09:54:43 +02:00
Stefan Zermatten
4d3fc3bb09 Fixed accidental back() requests when closing detail dialogs 2015-07-29 09:54:18 +02:00
Stefan Zermatten
4b984d4fac Made analytics show all characters as the same page 2015-07-29 09:53:46 +02:00
Stefan Zermatten
58843613ba Merge branch 'release-0.6.7' 2015-07-27 13:12:42 +02:00
Stefan Zermatten
39b549b24b Bumped version 2015-07-27 13:12:28 +02:00
Stefan Zermatten
c79177de72 Added Google Analytics 2015-07-27 13:10:33 +02:00
Stefan Zermatten
11d09b1487 Fixed effect values not being visible on mobile 2015-07-27 12:16:02 +02:00
Stefan Zermatten
0e4918d57d Merge branch 'hotfix-style' 2015-07-27 12:08:22 +02:00
Stefan Zermatten
949f313af2 removed 1st column of all tables being 100px 2015-07-27 12:08:15 +02:00
Stefan Zermatten
85b63f152f Merge branch 'release-0.6.6' into develop 2015-07-27 11:23:12 +02:00
Stefan Zermatten
2141d52a7a Merge branch 'release-0.6.6' 2015-07-27 11:22:41 +02:00
Stefan Zermatten
4c84235064 Bumped version 2015-07-27 11:22:26 +02:00
Stefan Zermatten
0e194a5408 Added markdown to text areas 2015-07-27 10:21:26 +02:00
Stefan Zermatten
4b60eac330 Fixed typo on change log 2015-07-24 11:52:46 +02:00
Stefan Zermatten
cb017c359d Merge branch 'release-0.6.5' into develop 2015-07-24 11:31:05 +02:00
Stefan Zermatten
15aaaa5c14 Merge branch 'release-0.6.5' 2015-07-24 11:29:50 +02:00
Stefan Zermatten
290bee83b4 Bumped version 2015-07-24 11:29:03 +02:00
Stefan Zermatten
fcd2461205 Merge branch 'master' into release-0.6.5 2015-07-24 11:26:46 +02:00
Stefan Zermatten
52198d0249 Disabled edit buttons for read-only viewers 2015-07-23 15:07:39 +02:00
Stefan Zermatten
ba7ccfdfa0 Added support for character profile pictures 2015-07-23 15:04:43 +02:00
Stefan Zermatten
92d3b086fa net worth calculations now take into account your containers' values 2015-07-23 09:14:55 +02:00
48 changed files with 315 additions and 96 deletions

1
rpg-docs/.gitignore vendored
View File

@@ -1,5 +1,6 @@
.meteor/local
.meteor/meteorite
settings.json
public/components
nohup.out
dump

View File

@@ -27,3 +27,5 @@ fourseven:scss@2.1.1
wolves:bourbon
meteorhacks:subs-manager
meteorhacks:kadira
chuangbo:marked
reywood:iron-router-ga

View File

@@ -14,6 +14,7 @@ blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
chuangbo:marked@0.3.5
coffeescript@1.0.6
dburles:collection-helpers@1.0.3
dburles:mongo-collection-instances@0.3.3
@@ -70,6 +71,7 @@ reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
retry@1.0.3
reywood:iron-router-ga@0.6.0
routepolicy@1.0.5
service-configuration@1.0.4
session@1.1.0

View File

@@ -7,6 +7,7 @@ Schemas.Character = new SimpleSchema({
alignment: {type: String, defaultValue: "", trim: false, optional: true},
gender: {type: String, defaultValue: "", trim: false, optional: true},
race: {type: String, defaultValue: "", trim: false, optional: true},
picture: {type: String, defaultValue: "", trim: true, 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},
@@ -32,6 +33,7 @@ Schemas.Character = new SimpleSchema({
age: {type: Schemas.Attribute},
ageRate: {type: Schemas.Attribute},
armor: {type: Schemas.Attribute},
carryMultiplier: {type: Schemas.Attribute},
//resources
level1SpellSlots: {type: Schemas.Attribute},

View File

@@ -107,6 +107,18 @@ if (Meteor.isServer) Characters.after.insert(function(userId, char) {
group: "Inate",
},
});
Effects.insert({
charId: char._id,
name: "Natural Carrying Capacity",
stat: "carryMultiplier",
operation: "base",
value: "1",
parent: {
id: char._id,
collection: "Characters",
group: "Inate",
},
});
});
Effects.attachBehaviour("softRemovable");

View File

@@ -30,7 +30,7 @@ Schemas.Proficiency = new SimpleSchema({
Proficiencies.attachSchema(Schemas.Proficiency);
Proficiencies.attachBehaviour("softRemovable");
makeChild(Proficiencies);
makeChild(Proficiencies, ["enabled"]);
Proficiencies.allow(CHARACTER_SUBSCHEMA_ALLOW);
Proficiencies.deny(CHARACTER_SUBSCHEMA_DENY);

View File

@@ -3,9 +3,9 @@ TemporaryHitPoints = new Mongo.Collection("temporaryHitPoints");
Schemas.TemporaryHitPoints = new SimpleSchema({
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
name: {type: String, optional: true},
maximum: {type: Number, defaultValue: 0},
used: {type: Number, defaultValue: 0},
deleteOnZero:{type: Boolean, defaultValue: true},
maximum: {type: Number, defaultValue: 0, min: 0, max: 500},
used: {type: Number, defaultValue: 0, min: 0, max: 500},
deleteOnZero:{type: Boolean, defaultValue: false},
dateAdded: {
type: Date,
autoValue: function() {

View File

@@ -1,6 +1,7 @@
Router.configure({
loadingTemplate: "loading",
layoutTemplate: "layout",
trackPageView: true,
});
Router.plugin("ensureSignedIn", {
@@ -56,6 +57,12 @@ Router.map(function() {
document.title = name;
}
},
//analytics
trackPageView: false,
onRun: function() {
window.ga && window.ga("send", "pageview", "/character");
this.next();
},
});
this.route("loading", {

View File

@@ -77,10 +77,10 @@ this.GlobalUI = (function() {
var throttleBack = _.throttle(function() {
history.back();
}, 800, {trailing: false});
}, 100, {trailing: false});
GlobalUI.closeDetail = function() {
if (!!(window.history && window.history.pushState)) {
if (window.history && history.pushState && history.state.detail === "opened") {
throttleBack();
} else {
Session.set("global.ui.detailShow", false);

View File

@@ -1,6 +1,10 @@
Template.registerHelper("canEditCharacter", function(charId) {
return canEditCharacter(charId);
});
canEditCharacter = function(charId) {
var char = Characters.findOne(charId)
var userId = Meteor.userId();
return char.owner === userId ||
_.contains(char.writers, userId);
});
};

View File

@@ -29,6 +29,11 @@ core-header-panel[drawer] {
box-shadow: 2px 0px 5px 0px rgba(0,0,0,0.2);
}
//Paragraphs
p {
margin-bottom: 8px;
}
//Horizontal rule
hr {
background-color: #444;
@@ -37,7 +42,7 @@ hr {
color: #444;
height: 1px;
line-height: 0;
margin: 16px -16px;
margin: 16px 0;
text-align: center;
}

View File

@@ -1,8 +1,5 @@
td {
padding: 8px;
&:nth-child(1) {
min-width: 100px;
}
}
.strengthTable{

View File

@@ -44,7 +44,8 @@
label="Value"
floatinglabel
value={{effectValue}}
flex>
flex
style="flex-basis: 100px;">
</paper-input>
</template>

View File

@@ -42,6 +42,7 @@ var stats = [
{stat: "rageDamage", name: "Rage Damage", group: "Stats"},
{stat: "expertiseDice", name: "Expertise Dice", group: "Stats"},
{stat: "superiorityDice", name: "Superiority Dice", group: "Stats"},
{stat: "carryMultiplier", name: "Carry Capacity Multiplier", group: "Stats"},
{stat: "level1SpellSlots", name: "level 1", group: "Spell Slots"},
{stat: "level2SpellSlots", name: "level 2", group: "Spell Slots"},
{stat: "level3SpellSlots", name: "level 3", group: "Spell Slots"},

View File

@@ -32,7 +32,7 @@
{{/if}}
{{#if description}}
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{/if}}
{{> effectsViewList charId=charId parentId=_id}}

View File

@@ -95,14 +95,16 @@
<core-tooltip label="Feature enabled"
position="left">
<paper-checkbox class="enabledCheckbox"
checked={{enabled}}>
checked={{enabled}}
disabled={{#unless canEditCharacter charId}}true{{/unless}}>
</paper-checkbox>
</core-tooltip>
{{/if}}
</div>
{{#if description}}
<div flex class="bottom text"
>{{evaluateString charId description}}</div>
<div flex class="bottom">
{{#markdown}}{{evaluateString charId shortDescription}}{{/markdown}}
</div>
{{/if}}
{{#if hasUses}}
<div layout horizontal center end-justified>

View File

@@ -3,14 +3,19 @@ Template.features.helpers({
var features = Features.find({charId: this._id}, {sort: {color: 1, name: 1}});
return features;
},
shortDescription: function() {
if (_.isString(this.description)){
return this.description.split(/^( *[-*_]){3,} *(?:\n+|$)/m)[0];
}
},
hasUses: function(){
return this.usesValue() > 0;
},
noUsesLeft: function(){
return this.usesLeft() <= 0;
return this.usesLeft() <= 0 || !canEditCharacter(this.charId);
},
usesFull: function(){
return this.usesLeft() >= this.usesValue();
return this.usesLeft() >= this.usesValue() || !canEditCharacter(this.charId);
},
colorClass: function(){
return getColorClass(this.color);
@@ -99,12 +104,12 @@ Template.resource.helpers({
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;
return !baseBigger || !canEditCharacter(this.char._id);
},
cantDecrement: function(){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
var valuePositive = value > 0;
return !valuePositive;
return !valuePositive || !canEditCharacter(this.char._id);
},
getColor: function(){
var value = Characters.calculate.attributeValue(this.char._id, this.name);

View File

@@ -14,7 +14,9 @@ var getFractionCarried = function(char) {
});
//get strength
var strength = Characters.calculate.attributeValue(char._id, "strength");
var capacity = strength * 15;
var carryMultiplier = Characters.calculate
.attributeValue(char._id, "carryMultiplier");
var capacity = strength * 15 * carryMultiplier;
return weight / capacity;
};

View File

@@ -41,6 +41,6 @@
</div>
{{#if description}}
<hr class="vertMargin">
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{/if}}
</template>

View File

@@ -35,8 +35,7 @@
<div class="item-slot">
<div class="item buff"
hero-id="main" {{detailHero}}
layout horizontal center
draggable="true">
layout horizontal center>
<div flex>
<core-icon icon="work"
style="margin-right: 16px">
@@ -114,6 +113,7 @@
</div>
<core-tooltip label="Container carried" position="left">
<paper-checkbox class="carriedCheckbox"
disabled={{#unless canEditCharacter charId}}true{{/unless}}
checked={{isCarried}}>
</paper-checkbox>
</core-tooltip>
@@ -152,11 +152,11 @@
<div class="item {{hidden}} inventoryItem"
hero-id="main" {{detailHero}}
layout horizontal center
draggable="true">
draggable={{canEditCharacter charId}}>
<div flex class="itemName">
{{#if ne1 quantity}}{{quantity}}&nbsp;{{/if}}{{pluralName}}
</div>
{{#if settings.showIncrement}}
{{#if settings.showIncrement}}{{#if canEditCharacter charId}}
<div class="incrementButtons">
<paper-icon-button class="addItemQuantity"
icon="add"
@@ -166,7 +166,7 @@
icon="remove"
style="margin-right: -8px"></paper-icon-button>
</div>
{{/if}}
{{/if}}{{/if}}
</div>
</div>
</template>

View File

@@ -44,6 +44,12 @@ Template.inventory.helpers({
).forEach(function(item){
worth += item.totalValue();
});
Containers.find(
{charId: this._id},
{fields: {value : 1}}
).forEach(function(container) {
if (container.value) worth += container.value;
});
return worth;
},
weightCarried: function(){

View File

@@ -18,8 +18,8 @@
{{#if requiresAttunement}}<div class="vertMargin">Requires Attunement</div>{{/if}}
</div>
{{#if description}}
<hr class="vertMargin">
<div class="pre-wrap">{{evaluateString charId description}}</div>
<hr style="margin: 16px 0 16px 0;">
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{/if}}
{{> effectsViewList charId=charId parentId=_id}}
{{> attacksViewList charId=charId parentId=_id}}

View File

@@ -6,7 +6,7 @@
</div>
{{#if description}}
<hr class="vertMargin">
<div class="pre-wrap">{{description}}</div>
<div>{{#markdown}}{{description}}{{/markdown}}</div>
{{/if}}
{{else}}
{{> experienceEdit}}

View File

@@ -10,7 +10,8 @@
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>
<paper-icon-button class="black54" id="addXP" icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}></paper-icon-button>
</div>
<div class="bottom list">
{{#each experiences}}
@@ -55,7 +56,8 @@
</div>
<paper-icon-button class="black54"
id="addClassButton"
icon="add">
icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
</paper-icon-button>
</div>
<div class="bottom list">
@@ -85,7 +87,7 @@
layout horizontal center>
{{name}}
</div>
<div class="bottom text">{{description}}</div>
<div class="bottom">{{#markdown}}{{description}}{{/markdown}}</div>
</paper-shadow>
{{/each}}
</div>

View File

@@ -1,7 +1,7 @@
<template name="noteDialog">
{{#with note}}
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
<div class="pre-wrap">{{description}}</div>
<div>{{#markdown}}{{description}}{{/markdown}}</div>
{{else}}
{{> noteDialogEdit}}
{{/baseDialog}}

View File

@@ -1,6 +1,6 @@
<template name="backgroundDialog">
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
<div class="pre-wrap">{{evaluateString charId value}}</div>
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true"}}
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
{{> proficiencyViewList charId=charId parentId=charId parentGroup="background"}}
{{else}}
{{> textDialogEdit}}

View File

@@ -1,18 +1,36 @@
<template name="personaDetailsDialog">
{{#baseDialog title=name class="deep-purple white-text" hideColor="true" hideDelete="true" startEditing=startEditing}}
{{alignment}} {{gender}} {{race}}
{{#with char}}
<div>{{alignment}} {{gender}} {{race}}</div>
<core-image style="width: 350px; height: 350px; margin-top: 8px;"
sizing="cover"
hero-id="image" hero
src={{picture}}></core-image>
{{/with}}
{{else}}
{{> personaDetailsEdit}}
{{#with char}}
{{> personaDetailsEdit}}
{{/with}}
{{/baseDialog}}
</template>
<template name="personaDetailsEdit">
<!--Name-->
<paper-input id="nameInput" label="Name" floatinglabel value={{name}}></paper-input><br>
<!--Alignment-->
<paper-input id="alignmentInput" label="Alignment" floatinglabel value={{alignment}}></paper-input><br>
<!--Gender-->
<paper-input id="genderInput" label="Gender" floatinglabel value={{gender}}></paper-input><br>
<!--Race-->
<paper-input id="raceInput" label="Race" floatinglabel value={{race}}></paper-input><br>
<div layout horizontal center-justified>
<div flex style="max-width: 350px;" layout vertical>
<!--Name-->
<paper-input id="nameInput" label="Name" floatinglabel value={{name}}></paper-input>
<!--Alignment-->
<paper-input id="alignmentInput" label="Alignment" floatinglabel value={{alignment}}></paper-input>
<!--Gender-->
<paper-input id="genderInput" label="Gender" floatinglabel value={{gender}}></paper-input>
<!--Race-->
<paper-input id="raceInput" label="Race" floatinglabel value={{race}}></paper-input>
<!--Picture-->
<paper-input id="pictureInput" label="Picture URL" floatinglabel value={{picture}}></paper-input>
<core-image style="height:350px; width: 100%; margin-top: 8px;"
sizing="cover"
hero-id="image" hero
src={{picture}}></core-image>
</div>
</div>
</template>

View File

@@ -2,21 +2,34 @@ Template.personaDetailsEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.personaDetailsDialog.helpers({
char: function() {
return Characters.findOne(
this._id,
{fields: {name: 1, alignment: 1, gender: 1, race: 1, picture: 1}}
);
}
});
Template.personaDetailsEdit.events({
"change #nameInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {name: input}});
Characters.update(this._id, {$set: {name: input}});
},
"change #alignmentInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {alignment: input}});
Characters.update(this._id, {$set: {alignment: input}});
},
"change #genderInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {gender: input}});
Characters.update(this._id, {$set: {gender: input}});
},
"change #raceInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {race: input}});
Characters.update(this._id, {$set: {race: input}});
},
"change #pictureInput": function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {$set: {picture: input}});
},
});

View File

@@ -3,7 +3,35 @@
<div id="persona" class="scroll-y" fit>
<div class="column-container">
{{#with characterDetails}}
{{#containerCardHelper this}}{{alignment}} {{gender}} {{race}}{{/containerCardHelper}}
<paper-shadow class="card"
hero-id="main" {{detailHero "details" _id}}>
{{#unless picture}}
<div class="top subhead characterField {{colorClass}}"
hero-id="toolbar" {{detailHero "details" _id}}>
<div class="subhead" flex
hero-id="title" {{detailHero "details" _id}}>
{{name}}
</div>
</div>
{{else}}
<core-image class="characterField clickable"
style="height:350px; width: 100%;
background-color: #e8e8e8;"
sizing="cover"
hero-id="image" {{detailHero "details" _id}}
src={{picture}}></core-image>
{{/unless}}
<div class="bottom">
{{#if picture}}
<div class="title" hero-id="title" {{detailHero "details" _id}}>
{{name}}
</div>
{{/if}}
<div class="subhead">
{{alignment}} {{gender}} {{race}}
</div>
</div>
</paper-shadow>
{{/with}}
{{> containerCard characterField "description" "Description"}}
{{> containerCard characterField "personality" "Personality Traits"}}
@@ -40,6 +68,6 @@
{{title}}
</div>
</div>
<div class="bottom text">{{> UI.contentBlock}}</div>
<div class="bottom">{{#markdown}}{{> UI.contentBlock}}{{/markdown}}</div>
</paper-shadow>
</template>

View File

@@ -11,12 +11,12 @@ Template.persona.helpers({
characterDetails: function(){
var char = Characters.findOne(
this._id,
{fields: {name: 1, gender: 1, alignment: 1, race:1}}
{fields: {name: 1, gender: 1, alignment: 1, race:1, picture: 1}}
);
char.field = "details";
char.title = char.name;
char.color = "d";
char.topClass = "characterField";
char.startEditing = true;
return char;
},
characterField: function(field, title){
@@ -40,7 +40,7 @@ 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",
@@ -58,6 +58,7 @@ Template.persona.events({
field: this.field,
title: this.title,
color: this.color,
startEditing: true,
},
heroId: this._id + this.field,
});

View File

@@ -1,6 +1,6 @@
<template name="textDialog">
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
<div class="pre-wrap">{{evaluateString charId value}}</div>
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
{{else}}
{{> textDialogEdit}}
{{/baseDialog}}

View File

@@ -34,7 +34,7 @@
</div>
{{/if}}
</div>
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{> attacksViewList charId=charId parentId=_id}}
</template>

View File

@@ -20,7 +20,7 @@
{{/if}}
</div>
<hr class="vertMargin">
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
</div>
{{else}}
<!--Name-->

View File

@@ -72,6 +72,7 @@
<core-tooltip label="Change prepared spells"
position="left">
<paper-icon-button class="prepSpells"
disabled={{#unless canEditCharacter charId}}true{{/unless}}
icon="book">
</paper-icon-button>
</core-tooltip>

View File

@@ -112,7 +112,7 @@ Template.spells.helpers({
for (i = 0; i < currentSlots; i++){
bubbles.push({
icon: "radio-button-on",
disabled: i !== currentSlots - 1, //last full slot not disabled
disabled: i !== currentSlots - 1 || !canEditCharacter(char._id), //last full slot not disabled
attribute: "level" + this.level + "SpellSlots",
charId: char._id,
});
@@ -120,7 +120,7 @@ Template.spells.helpers({
for (i = 0; i < slotsUsed; i++){
bubbles.push({
icon: "radio-button-off",
disabled: i !== 0, //first empty slot not disabled
disabled: i !== 0 || !canEditCharacter(char._id), //first empty slot not disabled
attribute: "level" + this.level + "SpellSlots",
charId: char._id,
});

View File

@@ -1,9 +1,11 @@
Template.addTHPDialog.events({
"tap #addButton": function(event, instance){
var max = +instance.find("#quantityInput").value;
if (!max || max < 0) max = 0;
TemporaryHitPoints.insert({
charId: this.charId,
name: instance.find("#nameInput").value,
maximum: +instance.find("#quantityInput").value,
maximum: max,
deleteOnZero: !!instance.find("#deleteWhenZeroCheckbox").checked,
});
}

View File

@@ -2,27 +2,27 @@
<table class="carryCapacityTable strengthTable">
<tr>
<td>Encumbered</td>
<td>&gt;{{evaluate charId "strength * 5"}}lbs</td>
<td>&gt;{{evaluate charId "strength * 5 * carryMultiplier"}}lbs</td>
<td class="caption">Variant rule, encumbered characters move 10 feet slower</td>
</tr>
<tr>
<td>Heavily encumbered</td>
<td>&gt;{{evaluate charId "strength * 10"}}lbs</td>
<td>&gt;{{evaluate charId "strength * 10 * carryMultiplier"}}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>&gt;{{evaluate charId "strength * 15"}}lbs</td>
<td>&gt;{{evaluate charId "strength * 15 * carryMultiplier"}}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>{{evaluate charId "strength * 30 * carryMultiplier"}}lbs</td>
<td class="caption"></td>
</tr>
</table>
</template>
</template>

View File

@@ -1,12 +1,16 @@
<template name="healthCard">
<paper-shadow class="card container healthCard"
hero-id="main" {{detailHero "hitPoints" _id}}
<paper-shadow class="card container healthCard"
hero-id="main" {{detailHero "hitPoints" _id}}
layout horizontal wrap>
<div class="green white-text subhead left"
<div class="green white-text subhead left"
hero-id="toolbar" {{detailHero "hitPoints" _id}}
layout vertical center center-justified>
<div class="hitPointTitle clickable">Hit Points</div>
<paper-icon-button class="white54" id="addTempHP" icon="add"></paper-icon-button>
<paper-icon-button class="white54"
id="addTempHP"
icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
</paper-icon-button>
</div>
<div class="right" flex layout vertical center-justified style="min-width: 180px;">
<div layout horizontal>
@@ -14,6 +18,7 @@
value={{characterCalculate "attributeValue" _id "hitPoints"}}
max={{characterCalculate "attributeBase" _id "hitPoints"}}
editable pin
disabled={{#unless canEditCharacter _id}}true{{/unless}}
role="slider">
</paper-diff-slider>
</div>
@@ -28,14 +33,14 @@
role="slider"
flex
></paper-diff-slider>
{{#unless left}}{{#unless deleteOnZero}}
{{#unless left}}
<paper-icon-button class="deleteTHP" icon="delete"></paper-icon-button>
{{/unless}}{{/unless}}
{{/unless}}
</div>
</div>
{{/each}}
<div class="caption">
{{#if multipliers.immunities.length}}
{{#if multipliers.immunities.length}}
<div>
Immune: {{#each multipliers.immunities}} {{name}} {{/each}}
</div>

View File

@@ -2,11 +2,11 @@ Template.hitDice.helpers({
cantIncrement: function(){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
var base = Characters.calculate.attributeBase(this.char._id, this.name);
return value >= base;
return value >= base || !canEditCharacter(this.char._id);
},
cantDecrement: function(){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
return value <= 0;
return value <= 0 || !canEditCharacter(this.char._id);
},
conMod: function(){
return signedString(

View File

@@ -45,6 +45,15 @@
</div>
<div class="bottom text">Lawful Good Human</div>
</paper-shadow>
<paper-shadow class="card characterCard ssWizard clickable"
z="2">
<div class="top subhead deep-purple white-text">
<div class="subhead" flex>
Starter Set Wizard
</div>
</div>
<div class="bottom text">Chaotic Good High Elf</div>
</paper-shadow>
</div>
</div>
</div>

View File

@@ -8,6 +8,9 @@ Template.intro.events({
"tap .ssArcher": function() {
Router.go("/character/yBWwt5XQTTHZiRQxq");
},
"tap .ssWizard": function() {
Router.go("/character/KxHKskm22fS2Xogah");
},
"tap .guideButton": function() {
Router.go("/guide");
},

View File

@@ -4,6 +4,9 @@
</core-toolbar>
<div fit layout vertical center center-justified>
<paper-spinner class="bigSpinner" active></paper-spinner>
<div class="subhead">{{randomHint}}</div>
<div class="subhead"
style="margin-left: 16px;
margin-right: 16px;
text-align: center;">{{randomHint}}</div>
</div>
</template>

View File

@@ -1,10 +1,14 @@
<template name="notFound">
<div layout vertical center center-justified fit>
<h2>The data for the page you requested could not be found.</h2>
<core-toolbar class="app-grey white-text">
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
</core-toolbar>
<div layout vertical center center-justified fit
style="padding: 16px; text-align: center;">
<h2 style="margin-bottom: 12px;">The data for the page you requested could not be found.</h2>
{{#if currentUser}}
<h2>It might not exist, or you might not have permission to view it.</h2>
<h3>It might not exist, or you might not have permission to view it.</h3>
{{else}}
<h2>Perhaps you need to sign in first:</h2>
<h3>Perhaps you need to sign in first:</h3>
{{atForm}}
{{/if}}
</div>

View File

@@ -9,20 +9,11 @@ Template.baseDialog.onRendered(function(){
Template.baseDialog.helpers({
editing: function(){
return Template.instance().editing.get();
return Template.instance().editing.get() && canEditCharacter(Template.parentData().charId);
},
showEdit: function() {
if (this.hideEdit) return false;
var charId = Template.parentData().charId;
var userId = Meteor.userId();
if (!userId) return false;
if (charId){
var char = Characters.findOne(charId);
if (char)
return char.owner === userId ||
_.contains(char.writers, userId);
}
return true;
return canEditCharacter(Template.parentData().charId);
},
});

View File

@@ -1,8 +1,13 @@
Meteor.methods({
"getUserId": function(username){
if (!username) return;
regex = new RegExp("^" + username + "$", "i")
var user = Meteor.users.findOne(
{$or: [{username: username}, {"emails.address": username}]}
{$or: [
{username: username},
{"emails.address": regex},
{"services.google.email": regex},
]}
);
return user && user._id;
}

View File

@@ -101,6 +101,8 @@ trackEncumbranceConditions = function(charId, templateInstance) {
{fields: {"settings": 1}}
);
var strength = Characters.calculate.attributeValue(charId, "strength");
var carryMultiplier = Characters.calculate
.attributeValue(charId, "carryMultiplier");
var give = function(condition) {
Meteor.call("giveCondition", charId, condition);
};
@@ -108,11 +110,11 @@ trackEncumbranceConditions = function(charId, templateInstance) {
Meteor.call("removeCondition", charId, condition);
};
//variant encumbrance rules
if (weight > strength * 10 &&
if (weight > strength * 10 * carryMultiplier &&
character.settings.useVariantEncumbrance) {
give("encumbered2");
remove("encumbered");
} else if (weight > strength * 5 &&
} else if (weight > strength * 5 * carryMultiplier &&
character.settings.useVariantEncumbrance){
give("encumbered");
remove("encumbered2");
@@ -121,11 +123,11 @@ trackEncumbranceConditions = function(charId, templateInstance) {
remove("encumbered2");
}
//normal encumbrance rules
if (weight > strength * 30 &&
if (weight > strength * 30 * carryMultiplier &&
character.settings.useStandardEncumbrance){
give("encumbered4");
remove("encumbered3");
} else if (weight > strength * 15 &&
} else if (weight > strength * 15 * carryMultiplier &&
character.settings.useStandardEncumbrance) {
give("encumbered3");
remove("encumbered4");

View File

@@ -219,3 +219,44 @@ ChangeLogs.insert({
"Skills should have correct min and max effects applied again",
],
});
ChangeLogs.insert({
version: "0.6.5",
changes: [
"Net worth now takes container values into account",
"Added support for character pictures",
"Disabled edit buttons for read-only viewers",
],
});
ChangeLogs.insert({
version: "0.6.6",
changes: [
"Text fields now accept github-flavor markdown formatting",
],
});
ChangeLogs.insert({
version: "0.6.7",
changes: [
"Fixed effect values not being visible on small screens",
"Added basic analytics",
],
});
ChangeLogs.insert({
version: "0.6.8",
changes: [
"Fixed share dialog not finding user names",
"Fixed temporary hitpoint sliders allowing negative values",
"Fixed proficiencies not being disabled with their features",
],
});
ChangeLogs.insert({
version: "0.7.0",
changes: [
"Added carry capacity multiplier as a stat with a default value of 1",
"Improved loading times by vulcanizing polymer imports",
],
});

View File

@@ -108,3 +108,45 @@ Migrations.add({
);
},
});
Migrations.add({
version: 4,
name: "Adds an effect to give characters a base carry capacity",
up: function() {
//update characters
Characters.find({}).forEach(function(char){
Characters.update(char._id, {
$set: {
carryMultiplier: {
adjustment: 0,
reset: "longRest",
}
}
});
var effect = Effects.findOne({
charId: char._id, name: "Natural Carrying Capacity"
});
if (effect) return;
Effects.insert({
charId: char._id,
name: "Natural Carrying Capacity",
stat: "carryMultiplier",
operation: "base",
value: "1",
parent: {
id: char._id,
collection: "Characters",
group: "Inate",
},
});
effect = Effects.findOne({
charId: char._id, name: "Natural Carrying Capacity"
});
if (!effect) throw "Carry capacity effect should be set by now."
});
},
down: function(){
return;
},
});