Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9368b06d0 | ||
|
|
2703367681 | ||
|
|
d419442549 | ||
|
|
99df01c950 | ||
|
|
d76349b3bb | ||
|
|
39c061f4e8 | ||
|
|
6d167ddb22 | ||
|
|
037acbd459 | ||
|
|
4d3fc3bb09 | ||
|
|
4b984d4fac | ||
|
|
58843613ba | ||
|
|
39b549b24b | ||
|
|
c79177de72 | ||
|
|
11d09b1487 | ||
|
|
0e4918d57d | ||
|
|
949f313af2 | ||
|
|
85b63f152f | ||
|
|
2141d52a7a | ||
|
|
4c84235064 | ||
|
|
0e194a5408 | ||
|
|
4b60eac330 | ||
|
|
cb017c359d | ||
|
|
15aaaa5c14 | ||
|
|
290bee83b4 | ||
|
|
fcd2461205 | ||
|
|
52198d0249 | ||
|
|
ba7ccfdfa0 | ||
|
|
92d3b086fa | ||
|
|
e180595dcd | ||
|
|
ed708bdde0 | ||
|
|
d7852d640f | ||
|
|
a2fdee88b6 | ||
|
|
af070b1578 | ||
|
|
83a8eeef0f | ||
|
|
34f8e7402b | ||
|
|
1b7e2cd850 | ||
|
|
463b7f0fc9 | ||
|
|
266495abc8 | ||
|
|
453d4365d3 | ||
|
|
e0ce6275bf | ||
|
|
16b16ce6c6 | ||
|
|
da8b91594e | ||
|
|
fc26f5a73e | ||
|
|
d2cc2833a9 |
1
rpg-docs/.gitignore
vendored
1
rpg-docs/.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.meteor/local
|
||||
.meteor/meteorite
|
||||
settings.json
|
||||
public/components
|
||||
nohup.out
|
||||
dump
|
||||
@@ -27,3 +27,5 @@ fourseven:scss@2.1.1
|
||||
wolves:bourbon
|
||||
meteorhacks:subs-manager
|
||||
meteorhacks:kadira
|
||||
chuangbo:marked
|
||||
reywood:iron-router-ga
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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},
|
||||
@@ -186,7 +187,7 @@ Schemas.Character = new SimpleSchema({
|
||||
|
||||
Characters.attachSchema(Schemas.Character);
|
||||
|
||||
var attributeBase = function(charId, statName){
|
||||
var attributeBase = preventLoop(function(charId, statName){
|
||||
check(statName, String);
|
||||
//if it's a damage multiplier, we treat it specially
|
||||
if (_.contains(DAMAGE_MULTIPLIERS, statName)){
|
||||
@@ -253,8 +254,8 @@ var attributeBase = function(charId, statName){
|
||||
if (result < min) result = min;
|
||||
if (result > max) result = max;
|
||||
|
||||
return result;
|
||||
};
|
||||
return Math.floor(result);
|
||||
});
|
||||
|
||||
if (Meteor.isClient) {
|
||||
Template.registerHelper("characterCalculate", function(func, charId, input) {
|
||||
@@ -324,9 +325,9 @@ Characters.calculate = {
|
||||
value += attribute.adjustment;
|
||||
return value;
|
||||
}),
|
||||
attributeBase: memoize(preventLoop(function(charId, attributeName){
|
||||
attributeBase: memoize(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
|
||||
@@ -345,8 +346,8 @@ Characters.calculate = {
|
||||
var value;
|
||||
var add = 0;
|
||||
var mul = 1;
|
||||
var min = Math.NEGATIVE_INFINITY;
|
||||
var max = Math.POSITIVE_INFINITY;
|
||||
var min = Number.NEGATIVE_INFINITY;
|
||||
var max = Number.POSITIVE_INFINITY;
|
||||
|
||||
Effects.find({
|
||||
charId: charId,
|
||||
@@ -369,7 +370,7 @@ Characters.calculate = {
|
||||
if (result < min) result = min;
|
||||
if (result > max) result = max;
|
||||
|
||||
return result;
|
||||
return Math.floor(result);
|
||||
})),
|
||||
proficiency: memoize(function(charId, skillName){
|
||||
//return largest value in proficiency array
|
||||
@@ -390,7 +391,7 @@ Characters.calculate = {
|
||||
});
|
||||
var advantage = Characters.calculate.advantage(charId, skillName);
|
||||
value += 5 * advantage;
|
||||
return value;
|
||||
return Math.floor(value);
|
||||
}),
|
||||
advantage: memoize(function(charId, skillName){
|
||||
var advantage = Effects.find(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -62,6 +62,7 @@ Spells.attachSchema(Schemas.Spell);
|
||||
|
||||
Spells.attachBehaviour("softRemovable");
|
||||
makeChild(Spells); //children of spell lists
|
||||
makeParent(Spells, ["name", "enabled"]); //parents of attacks
|
||||
|
||||
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Spells.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Router.configure({
|
||||
loadingTemplate: "loading",
|
||||
layoutTemplate: "layout",
|
||||
trackPageView: true,
|
||||
});
|
||||
|
||||
Router.plugin("ensureSignedIn", {
|
||||
@@ -27,7 +28,7 @@ Router.map(function() {
|
||||
},
|
||||
data: {
|
||||
characters: function(){
|
||||
return Characters.find({}, {fields: {_id: 1}});
|
||||
return Characters.find({}, {fields: {_id: 1}, sort: {name: 1}});
|
||||
}
|
||||
},
|
||||
onAfterAction: function() {
|
||||
@@ -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", {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
td {
|
||||
padding: 8px;
|
||||
&:nth-child(1) {
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.strengthTable{
|
||||
|
||||
@@ -3,26 +3,26 @@
|
||||
<div layout vertical flex>
|
||||
<div layout horizontal>
|
||||
<!--attackBonus-->
|
||||
<paper-input id="attackBonusInput"
|
||||
<paper-input class="attackBonusInput"
|
||||
label="Attack Bonus"
|
||||
floatinglabel
|
||||
value={{attackBonus}}
|
||||
flex></paper-input>
|
||||
<!--details-->
|
||||
<paper-input id="detailInput"
|
||||
<paper-input class="detailInput"
|
||||
label="Details"
|
||||
floatinglabel
|
||||
value={{details}}></paper-input>
|
||||
</div>
|
||||
<div layout horizontal>
|
||||
<!--damageBonus-->
|
||||
<paper-input id="damageInput"
|
||||
<paper-input class="damageInput"
|
||||
label="Damage"
|
||||
floatinglabel
|
||||
value={{damage}}
|
||||
flex></paper-input>
|
||||
<!--DamageType-->
|
||||
<paper-dropdown-menu id="damageTypeDropdown" label="Damage Type">
|
||||
<paper-dropdown-menu class="damageTypeDropdown" label="Damage Type">
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu" selected={{damageType}}>
|
||||
{{#each damageTypes}}
|
||||
@@ -34,6 +34,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<!--Delete Button-->
|
||||
<paper-icon-button id="deleteAttack" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
||||
<paper-icon-button class="deleteAttack" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -15,23 +15,23 @@ var damageTypes = [
|
||||
];
|
||||
|
||||
Template.attackEdit.events({
|
||||
"tap #deleteAttack": function(event, instance) {
|
||||
"tap .deleteAttack": function(event, instance) {
|
||||
Attacks.softRemoveNode(this._id);
|
||||
GlobalUI.deletedToast(this._id, "Attacks", "Attack");
|
||||
},
|
||||
"change #attackBonusInput": function(event) {
|
||||
"change .attackBonusInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
Attacks.update(this._id, {$set: {attackBonus: value}});
|
||||
},
|
||||
"change #damageInput": function(event) {
|
||||
"change .damageInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
Attacks.update(this._id, {$set: {damage: value}});
|
||||
},
|
||||
"change #detailInput": function(event) {
|
||||
"change .detailInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
Attacks.update(this._id, {$set: {details: value}});
|
||||
},
|
||||
"core-select #damageTypeDropdown": function(event) {
|
||||
"core-select .damageTypeDropdown": function(event) {
|
||||
var detail = event.originalEvent.detail;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
label="Value"
|
||||
floatinglabel
|
||||
value={{effectValue}}
|
||||
flex>
|
||||
flex
|
||||
style="flex-basis: 100px;">
|
||||
</paper-input>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,15 +104,16 @@ 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(){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
if (value > 0){
|
||||
return this.color;
|
||||
} else {
|
||||
return "grey";
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}} {{/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>
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</div>
|
||||
{{#if description}}
|
||||
<hr class="vertMargin">
|
||||
<div class="pre-wrap">{{description}}</div>
|
||||
<div>{{#markdown}}{{description}}{{/markdown}}</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{> experienceEdit}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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-->
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
{{characterCalculate "attributeValue" ../_id name}}
|
||||
</div>
|
||||
<div class="title white-text">
|
||||
d{{diceNum}} {{characterCalculate "abilityMod" ../_id "constitution"}}
|
||||
d{{diceNum}} {{conMod}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,16 @@ 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(
|
||||
Characters.calculate.abilityMod(this.char._id, "constitution")
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@ Template.characterSideList.helpers({
|
||||
{owner: userId},
|
||||
]
|
||||
},
|
||||
{fields: {name: 1}}
|
||||
{
|
||||
fields: {name: 1},
|
||||
sort: {name: 1},
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ function CacheObject(func, address, args, cache, context){
|
||||
var self = this;
|
||||
self.currentValue = null;
|
||||
self.dep = new Tracker.Dependency();
|
||||
self.numRun = 0;
|
||||
|
||||
//spawn a new autorun that keeps the value up-to-date
|
||||
Tracker.nonreactive(function() {
|
||||
@@ -26,8 +27,22 @@ function CacheObject(func, address, args, cache, context){
|
||||
delete cache[address];
|
||||
return;
|
||||
}
|
||||
//if we haven't run this before this flush, reset the counter after the flush
|
||||
if(self.numRun === 0){
|
||||
Tracker.afterFlush(function(){
|
||||
self.numRun = 0;
|
||||
});
|
||||
}
|
||||
self.numRun++;
|
||||
//call the expensive function
|
||||
//even if we don't use its value, we need to track its dependencies
|
||||
var newValue = func.apply(context, args);
|
||||
//prevent dependency loops, the memoized function shouldn't re-run
|
||||
//more than once per flush
|
||||
if (self.numRun > 1){
|
||||
newValue = NaN;
|
||||
if(_.isNaN(self.currentValue)) return;
|
||||
}
|
||||
//if the value changed, store the new value
|
||||
if (self.currentValue !== newValue){
|
||||
self.currentValue = newValue;
|
||||
|
||||
@@ -201,3 +201,45 @@ ChangeLogs.insert({
|
||||
],
|
||||
});
|
||||
|
||||
ChangeLogs.insert({
|
||||
version: "0.6.3",
|
||||
changes: [
|
||||
"Fixed a regression that stopped skills and attributes from rounding down correctly",
|
||||
"Made dependency loops return NaN immediately, rather than looping indefinitely until a page refresh. Adding an effect that adds \"strength\" to Strength, won't cause Strength to constantly increase or freeze the browser, Strength just becomes NaN",
|
||||
],
|
||||
});
|
||||
|
||||
ChangeLogs.insert({
|
||||
version: "0.6.4",
|
||||
changes: [
|
||||
"Hit dice now has a \"+\" between the dice and the constitution modifier",
|
||||
"Items with multiple attacks should have the damage type editable on all attacks now",
|
||||
"Spell attacks should now correctly inherit changes to their spell's name",
|
||||
"Character lists should now be ordered alphabetically",
|
||||
"Skills should have correct min and max effects applied again",
|
||||
],
|
||||
});
|
||||
|
||||
ChangeLogs.insert({
|
||||
version: "0.6.5",
|
||||
changes: [
|
||||
"Net worth now takes container values into account",
|
||||
"Added support for character pictures",
|
||||
"Disabled edit buttons for read-only viewers",
|
||||
],
|
||||
});
|
||||
|
||||
ChangeLogs.insert({
|
||||
version: "0.6.6",
|
||||
changes: [
|
||||
"Text fields now accept github-flavor markdown formatting",
|
||||
],
|
||||
});
|
||||
|
||||
ChangeLogs.insert({
|
||||
version: "0.6.7",
|
||||
changes: [
|
||||
"Fixed effect values not being visible on small screens",
|
||||
"Added basic analytics",
|
||||
],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user