Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6a9911dfc | ||
|
|
8a1871ee18 | ||
|
|
402f885f85 | ||
|
|
d07c118d47 | ||
|
|
103d44eeec | ||
|
|
33196c6771 | ||
|
|
80dc862047 | ||
|
|
314da14ad1 | ||
|
|
e5dbe81ac1 | ||
|
|
7e68ef64cc | ||
|
|
c9d71cad52 | ||
|
|
d79a808c81 | ||
|
|
1016c39bdf | ||
|
|
5f4923e049 | ||
|
|
e83237a728 | ||
|
|
9f323738bf | ||
|
|
1fc76fa50d | ||
|
|
36d5ff0a88 | ||
|
|
d05874ed13 | ||
|
|
df2521e69c | ||
|
|
3c6a685fe8 | ||
|
|
a77e560284 | ||
|
|
4cec83918f | ||
|
|
fec95c51c6 | ||
|
|
425c42d049 | ||
|
|
ab6f0c4f5b | ||
|
|
5d6e57b896 | ||
|
|
7c0a8125f2 | ||
|
|
7481ef08a8 | ||
|
|
b578dd5fb0 | ||
|
|
5d6f934d88 | ||
|
|
337f0bfa8a | ||
|
|
c62784894b | ||
|
|
75fff43d7d | ||
|
|
a9eeeac0df | ||
|
|
c8af0ff0a9 | ||
|
|
9e200db7b9 | ||
|
|
c08cf83096 | ||
|
|
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 | ||
|
|
80c72a274e | ||
|
|
91f0f7954c | ||
|
|
c74abcb608 | ||
|
|
da8b91594e | ||
|
|
fc26f5a73e | ||
|
|
4f60766d5d | ||
|
|
e992aeebef | ||
|
|
4108346a98 | ||
|
|
946fadadc2 | ||
|
|
d2cc2833a9 | ||
|
|
af57326194 | ||
|
|
98c69e9e17 | ||
|
|
395edd0563 | ||
|
|
43e87e7786 | ||
|
|
ad347504c6 | ||
|
|
4e6e99b695 | ||
|
|
104624a322 | ||
|
|
79d166e6af | ||
|
|
86c934e8ac | ||
|
|
a034cbf30e | ||
|
|
d5680ebf8a | ||
|
|
53f2fcc945 | ||
|
|
612e127be4 | ||
|
|
2b0d975cee | ||
|
|
248ab9bb6b | ||
|
|
314ce85410 | ||
|
|
9ff45dbcc2 | ||
|
|
6caf19bc99 | ||
|
|
c2b04d0977 | ||
|
|
9012c4a558 | ||
|
|
65a84937f2 | ||
|
|
eebb88b6b1 | ||
|
|
06ab7c5116 | ||
|
|
89f03c7601 | ||
|
|
9d2eb14c0c | ||
|
|
7b3cb54983 | ||
|
|
a09bad2fed | ||
|
|
afd897edfe | ||
|
|
efc79cb6e7 | ||
|
|
35efe39ea7 | ||
|
|
034067bd6e | ||
|
|
0d75cd5d15 | ||
|
|
4f1376a666 | ||
|
|
78b1d71b9d | ||
|
|
1323d8006c | ||
|
|
87d722adaf | ||
|
|
90e511eb00 | ||
|
|
5b8c25f5de | ||
|
|
2fbc54fee8 | ||
|
|
a064ae3fe8 | ||
|
|
ba9b518d7e |
60
README.md
60
README.md
@@ -1,58 +1,4 @@
|
||||
TODO
|
||||
====
|
||||
RPG Docs
|
||||
========
|
||||
|
||||
* Get Polymer installed using bower.
|
||||
* Install Vulcanize package listed below
|
||||
* Copy the differential polymer demo to get polymer implemented nicely
|
||||
* Update Meteor
|
||||
* Install and use LESS
|
||||
|
||||
Packages used
|
||||
=============
|
||||
|
||||
* meteor-platform
|
||||
* Base Meteor.
|
||||
* [Docs](http://docs.meteor.com/#/full/)
|
||||
* autopublish
|
||||
* Publishes everything to the client.
|
||||
* Must be removed before release
|
||||
* insecure
|
||||
* Allows the client the freedom to modify any colleciton.
|
||||
* Must be removed before release
|
||||
* iron:router
|
||||
* Enables pagination and URL's to direct to specific templates.
|
||||
* [Tutorial](http://www.manuel-schoebel.com/blog/iron-router-tutorial)
|
||||
* accounts-password
|
||||
* Lets users create accounts with a simple password
|
||||
* accounts-ui
|
||||
* Adds simple UI for logging in
|
||||
* random
|
||||
* Somewhat decent cryptographically strong psuedo random number generation.
|
||||
* [readme](https://atmospherejs.com/meteor/random)
|
||||
* dburles:collection-helpers
|
||||
* Adds template-style helpers to collections. [github page](https://github.com/dburles/meteor-collection-helpers)
|
||||
* reactive-var
|
||||
* Friendly reactive variables
|
||||
* [Meteor Docs](http://docs.meteor.com/#/full/reactivevar_pkg)
|
||||
* cw4gn3r:jquery-event-drag
|
||||
* Adds jquery drag events
|
||||
* underscore
|
||||
* Handy javascript utilities
|
||||
* [Docs](http://underscorejs.org/)
|
||||
* aldeed:collection2
|
||||
* Extends collections with Schemas
|
||||
* [(gitHub page)](https://github.com/aldeed/meteor-collection2)
|
||||
* uses [SimpleSchema](https://github.com/aldeed/meteor-simple-schema)
|
||||
* aldeed:autoform
|
||||
* Automatically generates bootstrap forms for collection2 Schemas.
|
||||
* [github](https://github.com/aldeed/meteor-autoform)
|
||||
* differential:vulcanize
|
||||
* Bakes all the polymer imports into one file
|
||||
* [github](https://github.com/Differential/meteor-vulcanize)
|
||||
|
||||
************
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
[differential's polymer demo](https://github.com/Differential/polymer-demo)
|
||||
This is the repo for [DiceCloud](dicecloud.com). The currently deployed version should always be the head of the master branch.
|
||||
|
||||
5
rpg-docs/.gitignore
vendored
5
rpg-docs/.gitignore
vendored
@@ -1,5 +1,8 @@
|
||||
.meteor/local
|
||||
.meteor/meteorite
|
||||
.demeteorized
|
||||
packages
|
||||
settings.json
|
||||
public/components
|
||||
nohup.out
|
||||
dump
|
||||
dump
|
||||
|
||||
@@ -6,3 +6,7 @@ notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
notices-for-facebook-graph-api-2
|
||||
1.2.0-standard-minifiers-package
|
||||
1.2.0-meteor-platform-split
|
||||
1.2.0-cordova-changes
|
||||
1.2.0-breaking-changes
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
meteor-platform
|
||||
thaum:vulcanize@0.0.5
|
||||
iron:router
|
||||
accounts-password
|
||||
accounts-ui
|
||||
@@ -12,7 +12,6 @@ dburles:collection-helpers
|
||||
reactive-var
|
||||
underscore
|
||||
aldeed:collection2
|
||||
differential:vulcanize
|
||||
matb33:collection-hooks
|
||||
zimme:collection-softremovable
|
||||
momentjs:moment
|
||||
@@ -26,3 +25,22 @@ email
|
||||
fourseven:scss@2.1.1
|
||||
wolves:bourbon
|
||||
meteorhacks:subs-manager
|
||||
meteorhacks:kadira
|
||||
chuangbo:marked
|
||||
reywood:iron-router-ga
|
||||
standard-minifiers
|
||||
meteor-base
|
||||
mobile-experience
|
||||
mongo
|
||||
blaze-html-templates
|
||||
session
|
||||
jquery
|
||||
tracker
|
||||
logging
|
||||
reload
|
||||
ejson
|
||||
spacebars
|
||||
check
|
||||
useraccounts:iron-routing
|
||||
wizonesolutions:canonical
|
||||
meteorhacks:fast-render
|
||||
|
||||
@@ -1 +1 @@
|
||||
METEOR@1.1.0.2
|
||||
METEOR@1.2.0.2
|
||||
|
||||
@@ -1,91 +1,121 @@
|
||||
accounts-base@1.2.0
|
||||
accounts-google@1.0.4
|
||||
accounts-oauth@1.1.5
|
||||
accounts-password@1.1.1
|
||||
accounts-ui@1.1.5
|
||||
accounts-ui-unstyled@1.1.7
|
||||
aldeed:collection2@2.3.3
|
||||
accounts-base@1.2.1
|
||||
accounts-google@1.0.6
|
||||
accounts-oauth@1.1.7
|
||||
accounts-password@1.1.3
|
||||
accounts-ui@1.1.6
|
||||
accounts-ui-unstyled@1.1.8
|
||||
aldeed:collection2@2.5.0
|
||||
aldeed:simple-schema@1.3.3
|
||||
autoupdate@1.2.1
|
||||
base64@1.0.3
|
||||
binary-heap@1.0.3
|
||||
blaze@2.1.2
|
||||
blaze-tools@1.0.3
|
||||
boilerplate-generator@1.0.3
|
||||
callback-hook@1.0.3
|
||||
check@1.0.5
|
||||
coffeescript@1.0.6
|
||||
autoupdate@1.2.3
|
||||
babel-compiler@5.8.24_1
|
||||
babel-runtime@0.1.4
|
||||
base64@1.0.4
|
||||
binary-heap@1.0.4
|
||||
blaze@2.1.3
|
||||
blaze-html-templates@1.0.1
|
||||
blaze-tools@1.0.4
|
||||
boilerplate-generator@1.0.4
|
||||
caching-compiler@1.0.0
|
||||
caching-html-compiler@1.0.2
|
||||
callback-hook@1.0.4
|
||||
check@1.0.6
|
||||
chuangbo:cookie@1.1.0
|
||||
chuangbo:marked@0.3.5_1
|
||||
coffeescript@1.0.10
|
||||
dburles:collection-helpers@1.0.3
|
||||
dburles:mongo-collection-instances@0.3.3
|
||||
ddp@1.1.0
|
||||
deps@1.0.7
|
||||
differential:vulcanize@0.0.5
|
||||
dburles:mongo-collection-instances@0.3.4
|
||||
ddp@1.2.2
|
||||
ddp-client@1.2.1
|
||||
ddp-common@1.2.1
|
||||
ddp-rate-limiter@1.0.0
|
||||
ddp-server@1.2.1
|
||||
deps@1.0.9
|
||||
diff-sequence@1.0.1
|
||||
ecmascript@0.1.5
|
||||
ecmascript-collections@0.1.6
|
||||
ecwyne:mathjs@0.25.0
|
||||
ejson@1.0.6
|
||||
email@1.0.6
|
||||
fastclick@1.0.3
|
||||
ejson@1.0.7
|
||||
email@1.0.7
|
||||
fastclick@1.0.7
|
||||
fourseven:scss@2.1.1
|
||||
geojson-utils@1.0.3
|
||||
google@1.1.5
|
||||
html-tools@1.0.4
|
||||
htmljs@1.0.4
|
||||
http@1.1.0
|
||||
id-map@1.0.3
|
||||
iron:controller@1.0.7
|
||||
iron:core@1.0.7
|
||||
iron:dynamic-template@1.0.7
|
||||
iron:layout@1.0.7
|
||||
iron:location@1.0.7
|
||||
iron:middleware-stack@1.0.7
|
||||
iron:router@1.0.7
|
||||
iron:url@1.0.7
|
||||
jquery@1.11.3_2
|
||||
json@1.0.3
|
||||
lai:collection-extensions@0.1.3
|
||||
launch-screen@1.0.2
|
||||
less@1.0.14
|
||||
livedata@1.0.13
|
||||
localstorage@1.0.3
|
||||
logging@1.0.7
|
||||
matb33:collection-hooks@0.7.13
|
||||
meteor@1.1.6
|
||||
meteor-platform@1.2.2
|
||||
meteorhacks:subs-manager@1.3.0
|
||||
minifiers@1.1.5
|
||||
minimongo@1.0.8
|
||||
mobile-status-bar@1.0.3
|
||||
momentjs:moment@2.10.3
|
||||
mongo@1.1.0
|
||||
geojson-utils@1.0.4
|
||||
google@1.1.6
|
||||
hot-code-push@1.0.0
|
||||
html-tools@1.0.5
|
||||
htmljs@1.0.5
|
||||
http@1.1.1
|
||||
id-map@1.0.4
|
||||
iron:controller@1.0.8
|
||||
iron:core@1.0.8
|
||||
iron:dynamic-template@1.0.8
|
||||
iron:layout@1.0.8
|
||||
iron:location@1.0.9
|
||||
iron:middleware-stack@1.0.9
|
||||
iron:router@1.0.9
|
||||
iron:url@1.0.9
|
||||
jquery@1.11.4
|
||||
lai:collection-extensions@0.1.4
|
||||
launch-screen@1.0.4
|
||||
less@2.5.0_3
|
||||
livedata@1.0.15
|
||||
localstorage@1.0.5
|
||||
logging@1.0.8
|
||||
matb33:collection-hooks@0.8.1
|
||||
meteor@1.1.9
|
||||
meteor-base@1.0.1
|
||||
meteorhacks:fast-render@2.10.0
|
||||
meteorhacks:inject-data@1.4.1
|
||||
meteorhacks:kadira@2.23.4
|
||||
meteorhacks:meteorx@1.3.1
|
||||
meteorhacks:picker@1.0.3
|
||||
meteorhacks:subs-manager@1.6.2
|
||||
minifiers@1.1.7
|
||||
minimongo@1.0.10
|
||||
mobile-experience@1.0.1
|
||||
mobile-status-bar@1.0.6
|
||||
momentjs:moment@2.10.6
|
||||
mongo@1.1.2
|
||||
mongo-id@1.0.1
|
||||
mongo-livedata@1.0.9
|
||||
npm-bcrypt@0.7.8_2
|
||||
oauth@1.1.4
|
||||
oauth2@1.1.3
|
||||
observe-sequence@1.0.6
|
||||
ordered-dict@1.0.3
|
||||
percolate:migrations@0.7.5
|
||||
random@1.0.3
|
||||
reactive-dict@1.1.0
|
||||
reactive-var@1.0.5
|
||||
reload@1.1.3
|
||||
retry@1.0.3
|
||||
routepolicy@1.0.5
|
||||
service-configuration@1.0.4
|
||||
session@1.1.0
|
||||
sha@1.0.3
|
||||
npm-mongo@1.4.39_1
|
||||
oauth@1.1.6
|
||||
oauth2@1.1.5
|
||||
observe-sequence@1.0.7
|
||||
ordered-dict@1.0.4
|
||||
percolate:migrations@0.9.6
|
||||
promise@0.5.0
|
||||
random@1.0.4
|
||||
rate-limit@1.0.0
|
||||
reactive-dict@1.1.2
|
||||
reactive-var@1.0.6
|
||||
reload@1.1.4
|
||||
retry@1.0.4
|
||||
reywood:iron-router-ga@0.7.1
|
||||
routepolicy@1.0.6
|
||||
service-configuration@1.0.5
|
||||
session@1.1.1
|
||||
sha@1.0.4
|
||||
softwarerero:accounts-t9n@1.0.9
|
||||
spacebars@1.0.6
|
||||
spacebars-compiler@1.0.6
|
||||
spacebars@1.0.7
|
||||
spacebars-compiler@1.0.7
|
||||
splendido:accounts-emails-field@1.2.0
|
||||
splendido:accounts-meld@1.3.0
|
||||
srp@1.0.3
|
||||
templating@1.1.1
|
||||
tracker@1.0.7
|
||||
ui@1.0.6
|
||||
underscore@1.0.3
|
||||
url@1.0.4
|
||||
useraccounts:core@1.9.1
|
||||
useraccounts:polymer@1.9.1
|
||||
webapp@1.2.0
|
||||
webapp-hashing@1.0.3
|
||||
wolves:bourbon@1.0.0
|
||||
zimme:collection-behaviours@1.0.4
|
||||
splendido:accounts-meld@1.3.1
|
||||
srp@1.0.4
|
||||
standard-minifiers@1.0.1
|
||||
templating@1.1.4
|
||||
templating-tools@1.0.0
|
||||
thaum:vulcanize@0.0.5
|
||||
tracker@1.0.9
|
||||
ui@1.0.8
|
||||
underscore@1.0.4
|
||||
url@1.0.5
|
||||
useraccounts:core@1.12.3
|
||||
useraccounts:iron-routing@1.12.3
|
||||
useraccounts:polymer@1.12.3
|
||||
webapp@1.2.2
|
||||
webapp-hashing@1.0.5
|
||||
wizonesolutions:canonical@0.0.5
|
||||
wolves:bourbon@1.2.0
|
||||
zimme:collection-behaviours@1.1.3
|
||||
zimme:collection-softremovable@1.0.4
|
||||
|
||||
@@ -7,6 +7,7 @@ Schemas.Action = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
|
||||
@@ -7,6 +7,7 @@ Schemas.Attack = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
@@ -69,5 +70,17 @@ Attacks.attachSchema(Schemas.Attack);
|
||||
Attacks.attachBehaviour("softRemovable");
|
||||
makeChild(Attacks, ["name", "enabled"]); //children of lots of things
|
||||
|
||||
Attacks.after.insert(function (userId, attack) {
|
||||
//Check to see if this attack's parent is a spell, if so, mirror prepared state to enabled
|
||||
if (attack.parent.collection === "Spells") {
|
||||
var parentSpell = Spells.findOne(attack.parent.id);
|
||||
if (parentSpell.prepared === "unprepared") {
|
||||
Attacks.update(attack._id, {$set: {enabled: false}});
|
||||
} else if (parentSpell.prepared === "prepared" || "always") {
|
||||
Attacks.update(attack._id, {$set: {enabled: true}});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Attacks.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Attacks.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -4,6 +4,7 @@ Schemas.Buff = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
|
||||
@@ -3,16 +3,17 @@ Characters = new Mongo.Collection("characters");
|
||||
|
||||
Schemas.Character = new SimpleSchema({
|
||||
//strings
|
||||
name: {type: String, defaultValue: "", trim: false},
|
||||
alignment: {type: String, defaultValue: "", trim: false},
|
||||
gender: {type: String, defaultValue: "", trim: false},
|
||||
race: {type: String, defaultValue: "", trim: false},
|
||||
description: {type: String, defaultValue: "", trim: false},
|
||||
personality: {type: String, defaultValue: "", trim: false},
|
||||
ideals: {type: String, defaultValue: "", trim: false},
|
||||
bonds: {type: String, defaultValue: "", trim: false},
|
||||
flaws: {type: String, defaultValue: "", trim: false},
|
||||
backstory: {type: String, defaultValue: "", trim: false},
|
||||
name: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
alignment: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
gender: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
race: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
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},
|
||||
bonds: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
flaws: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
backstory: {type: String, defaultValue: "", trim: false, optional: true},
|
||||
|
||||
//attributes
|
||||
//ability scores
|
||||
@@ -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},
|
||||
@@ -159,6 +161,7 @@ Schemas.Character = new SimpleSchema({
|
||||
deathSave: {type: Schemas.DeathSave},
|
||||
|
||||
//permissions
|
||||
party: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true},
|
||||
owner: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
|
||||
writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
|
||||
@@ -173,99 +176,117 @@ Schemas.Character = new SimpleSchema({
|
||||
//slowed down by carrying too much?
|
||||
"settings.useVariantEncumbrance": {type: Boolean, defaultValue: false},
|
||||
"settings.useStandardEncumbrance": {type: Boolean, defaultValue: true},
|
||||
//hide spellcasting
|
||||
"settings.hideSpellcasting": {type: Boolean, defaultValue: false},
|
||||
//show to anyone with link
|
||||
"settings.viewPermission": {
|
||||
type: String,
|
||||
defaultValue: "whitelist",
|
||||
allowedValues: ["whitelist", "public"],
|
||||
},
|
||||
});
|
||||
|
||||
Characters.attachSchema(Schemas.Character);
|
||||
|
||||
var attributeBase = function(charId, statName){
|
||||
var attributeBase = preventLoop(function(charId, statName){
|
||||
check(statName, String);
|
||||
//if it's a damage multiplier, we treat it specially
|
||||
if (_.contains(DAMAGE_MULTIPLIERS, statName)){
|
||||
var effects = Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true, operation: "mul"}
|
||||
).fetch();
|
||||
var resistCount = 0;
|
||||
var vulnCount = 0;
|
||||
var multiplierEvaluationFail = false;
|
||||
_.each(effects, function(effect){
|
||||
var val = evaluateEffect(charId, effect);
|
||||
if (val === 0.5){ //resistance
|
||||
resistCount += 1;
|
||||
} else if (val === 2){ //vulnerability
|
||||
vulnCount += 1;
|
||||
} else if (val === 0){ //imunity
|
||||
return 0; //imunity is absolute
|
||||
} else {
|
||||
multiplierEvaluationFail = true;
|
||||
}
|
||||
});
|
||||
if (multiplierEvaluationFail){
|
||||
//we can't work it out correctly, set the value to 1
|
||||
//and try work it out using regular maths below
|
||||
value = 1;
|
||||
} else if (resistCount && !vulnCount){
|
||||
var invulnerabilityCount = Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: "mul",
|
||||
value: 0,
|
||||
}).count();
|
||||
if (invulnerabilityCount) return 0;
|
||||
var resistCount = Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: "mul",
|
||||
value: 0.5,
|
||||
}).count();
|
||||
var vulnCount = Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: "mul",
|
||||
value: 2,
|
||||
}).count();
|
||||
if (!resistCount && !vulnCount){
|
||||
return 1;
|
||||
} else if (resistCount && !vulnCount){
|
||||
return 0.5;
|
||||
} else if (!resistCount && vulnCount){
|
||||
} else if (!resistCount && vulnCount){
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
var value;
|
||||
var base = 0;
|
||||
var add = 0;
|
||||
var mul = 1;
|
||||
var min = Number.NEGATIVE_INFINITY;
|
||||
var max = Number.POSITIVE_INFINITY;
|
||||
|
||||
var value = 0;
|
||||
|
||||
//start with the highest base value
|
||||
Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true, operation: "base"}
|
||||
).forEach(function(effect){
|
||||
var efv = evaluateEffect(charId, effect);
|
||||
if (efv > value){
|
||||
value = efv;
|
||||
Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||
}).forEach(function(effect) {
|
||||
value = evaluateEffect(charId, effect);
|
||||
if (effect.operation === "base"){
|
||||
if (value > base) base = value;
|
||||
} else if (effect.operation === "add"){
|
||||
add += value;
|
||||
} else if (effect.operation === "mul"){
|
||||
mul *= value;
|
||||
} else if (effect.operation === "min"){
|
||||
if (value > min) min = value;
|
||||
} else if (effect.operation === "max"){
|
||||
if (value < max) max = value;
|
||||
}
|
||||
});
|
||||
|
||||
//add all the add values
|
||||
Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true, operation: "add"}
|
||||
).forEach(function(effect){
|
||||
value += evaluateEffect(charId, effect);
|
||||
});
|
||||
var result = (base + add) * mul;
|
||||
if (result < min) result = min;
|
||||
if (result > max) result = max;
|
||||
|
||||
//multiply all the mul values
|
||||
Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true, operation: "mul"}
|
||||
).forEach(function(effect){
|
||||
value *= evaluateEffect(charId, effect);
|
||||
});
|
||||
return Math.floor(result);
|
||||
});
|
||||
|
||||
//ensure value is >= all mins
|
||||
Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true, operation: "min"}
|
||||
).forEach(function(effect){
|
||||
var min = evaluateEffect(charId, effect);
|
||||
value = value > min ? value : min;
|
||||
if (Meteor.isClient) {
|
||||
Template.registerHelper("characterCalculate", function(func, charId, input) {
|
||||
try {
|
||||
return Characters.calculate[func](charId, input);
|
||||
} catch (e){
|
||||
if (!Characters.calculate[func]){
|
||||
throw new Error(func + "is not a function name");
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//ensure value is <= all maxes
|
||||
Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true, operation: "max"}
|
||||
).forEach(function(effect){
|
||||
var max = evaluateEffect(charId, effect);
|
||||
value = value < max ? value : max;
|
||||
//create a local memoize with a argument concatenating hash function
|
||||
var memoize = function(f) {
|
||||
return Tracker.memoize(f, function() {
|
||||
return _.reduce(arguments, function(memo, arg) {
|
||||
return memo + arg;
|
||||
}, "");
|
||||
});
|
||||
return value;
|
||||
};
|
||||
|
||||
//functions and calculated values.
|
||||
//These functions can only rely on this._id since no other
|
||||
//field is likely to be attached to all returned characters
|
||||
Characters.helpers({
|
||||
//returns the value stored in the field requested
|
||||
//will set up dependencies on just that field
|
||||
getField : function(fieldName){
|
||||
//memoize funcitons that have finds and slow loops
|
||||
Characters.calculate = {
|
||||
getField: function(charId, fieldName) {
|
||||
var fieldSelector = {};
|
||||
fieldSelector[fieldName] = 1;
|
||||
var char = Characters.findOne(this._id, {fields: fieldSelector});
|
||||
var char = Characters.findOne(charId, {fields: fieldSelector});
|
||||
var field = char[fieldName];
|
||||
if (field === undefined){
|
||||
throw new Meteor.Error(
|
||||
@@ -278,8 +299,7 @@ Characters.helpers({
|
||||
}
|
||||
return field;
|
||||
},
|
||||
//returns the value of a field
|
||||
fieldValue : function(fieldName){
|
||||
fieldValue: function(charId, fieldName) {
|
||||
if (!Schemas.Character.schema(fieldName)){
|
||||
throw new Meteor.Error(
|
||||
"Field not found",
|
||||
@@ -289,102 +309,92 @@ Characters.helpers({
|
||||
//duck typing to get the right value function
|
||||
//.ability implies skill
|
||||
if (Schemas.Character.schema(fieldName + ".ability")){
|
||||
return this.skillMod(fieldName);
|
||||
return Characters.calculate.skillMod(charId, fieldName);
|
||||
}
|
||||
//adjustment implies attribute
|
||||
if (Schemas.Character.schema(fieldName + ".adjustment")){
|
||||
return this.attributeValue(fieldName);
|
||||
return Characters.calculate.attributeValue(charId, fieldName);
|
||||
}
|
||||
//fall back to just returning the field itself
|
||||
return this.getField(fieldName);
|
||||
return Characters.calculate.getField(charId, fieldName);
|
||||
},
|
||||
|
||||
attributeValue: function(attributeName){
|
||||
var charId = this._id;
|
||||
var attribute = this.getField(attributeName);
|
||||
attributeValue: memoize(function(charId, attributeName){
|
||||
var attribute = Characters.calculate.getField(charId, attributeName);
|
||||
//base value
|
||||
var value = this.attributeBase(attributeName);
|
||||
var value = Characters.calculate.attributeBase(charId, attributeName);
|
||||
//plus adjustment
|
||||
value += attribute.adjustment;
|
||||
return value;
|
||||
},
|
||||
|
||||
attributeBase: preventLoop(function(attributeName){
|
||||
var charId = this._id;
|
||||
//base value
|
||||
}),
|
||||
attributeBase: memoize(function(charId, attributeName){
|
||||
return attributeBase(charId, attributeName);
|
||||
}),
|
||||
|
||||
skillMod: preventLoop(function(skillName){
|
||||
var charId = this._id;
|
||||
var skill = this.getField(skillName);
|
||||
skillMod: memoize(preventLoop(function(charId, skillName){
|
||||
var skill = Characters.calculate.getField(charId, skillName);
|
||||
//get the final value of the ability score
|
||||
var ability = this.attributeValue(skill.ability);
|
||||
var ability = Characters.calculate.attributeValue(charId, skill.ability);
|
||||
|
||||
//base modifier
|
||||
var mod = +getMod(ability);
|
||||
|
||||
//multiply proficiency bonus by largest value in proficiency array
|
||||
var prof = this.proficiency(skillName);
|
||||
var prof = Characters.calculate.proficiency(charId, skillName);
|
||||
|
||||
//add multiplied proficiency bonus to modifier
|
||||
mod += prof * this.attributeValue("proficiencyBonus");
|
||||
mod += prof * Characters.calculate.attributeValue(charId, "proficiencyBonus");
|
||||
|
||||
//apply all effects
|
||||
var rawEffects = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true}
|
||||
).fetch();
|
||||
var effects = _.groupBy(rawEffects, "operation");
|
||||
_.forEach(effects.add, function(effect){
|
||||
mod += evaluateEffect(charId, effect);
|
||||
});
|
||||
_.forEach(effects.mul, function(effect){
|
||||
mod *= evaluateEffect(charId, effect);
|
||||
});
|
||||
_.forEach(effects.min, function(effect){
|
||||
var min = evaluateEffect(charId, effect);
|
||||
mod = mod > min ? mod : min;
|
||||
});
|
||||
_.forEach(effects.max, function(effect){
|
||||
var max = evaluateEffect(charId, effect);
|
||||
mod = mod < max ? mod : max;
|
||||
});
|
||||
return signedString(mod);
|
||||
}),
|
||||
var value;
|
||||
var add = 0;
|
||||
var mul = 1;
|
||||
var min = Number.NEGATIVE_INFINITY;
|
||||
var max = Number.POSITIVE_INFINITY;
|
||||
|
||||
proficiency: function(skillName){
|
||||
var charId = this._id;
|
||||
//return largest value in proficiency array
|
||||
var prof = 0;
|
||||
Proficiencies.find(
|
||||
{charId: charId, name: skillName, enabled: true}
|
||||
).forEach(function(proficiency){
|
||||
var newProf = proficiency.value;
|
||||
if (newProf > prof){
|
||||
prof = newProf;
|
||||
Effects.find({
|
||||
charId: charId,
|
||||
stat: skillName,
|
||||
enabled: true,
|
||||
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||
}).forEach(function(effect) {
|
||||
value = evaluateEffect(charId, effect);
|
||||
if (effect.operation === "add"){
|
||||
add += value;
|
||||
} else if (effect.operation === "mul"){
|
||||
mul *= value;
|
||||
} else if (effect.operation === "min"){
|
||||
if (value > min) min = value;
|
||||
} else if (effect.operation === "max"){
|
||||
if (value < max) max = value;
|
||||
}
|
||||
});
|
||||
return prof;
|
||||
},
|
||||
var result = (mod + add) * mul;
|
||||
if (result < min) result = min;
|
||||
if (result > max) result = max;
|
||||
|
||||
passiveSkill: function(skillName){
|
||||
if (_.isString(skillName)){
|
||||
var skill = this.getField(skillName);
|
||||
}
|
||||
var charId = this._id;
|
||||
var mod = +this.skillMod(skillName);
|
||||
return Math.floor(result);
|
||||
})),
|
||||
proficiency: memoize(function(charId, skillName){
|
||||
//return largest value in proficiency array
|
||||
var prof = Proficiencies.findOne(
|
||||
{charId: charId, name: skillName, enabled: true},
|
||||
{sort: {value: -1}}
|
||||
);
|
||||
return prof && prof.value || 0;
|
||||
}),
|
||||
passiveSkill: memoize(function(charId, skillName){
|
||||
var skill = Characters.calculate.getField(charId, skillName);
|
||||
var mod = +Characters.calculate.skillMod(charId, skillName);
|
||||
var value = 10 + mod;
|
||||
Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"}
|
||||
).forEach(function(effect){
|
||||
value += evaluateEffect(charId, effect);
|
||||
});
|
||||
return value;
|
||||
//TODO decide whether (dis)advantage gives (-)+5 to passive checks
|
||||
},
|
||||
|
||||
advantage: function(skillName){
|
||||
var charId = this._id;
|
||||
var advantage = Characters.calculate.advantage(charId, skillName);
|
||||
value += 5 * advantage;
|
||||
return Math.floor(value);
|
||||
}),
|
||||
advantage: memoize(function(charId, skillName){
|
||||
var advantage = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "advantage"}
|
||||
).count();
|
||||
@@ -394,19 +404,18 @@ Characters.helpers({
|
||||
if (advantage && !disadvantage) return 1;
|
||||
if (disadvantage && !advantage) return -1;
|
||||
return 0;
|
||||
}),
|
||||
abilityMod: function(charId, attribute){
|
||||
return getMod(
|
||||
Characters.calculate.attributeValue(charId, attribute)
|
||||
);
|
||||
},
|
||||
|
||||
abilityMod: function(attribute){
|
||||
return signedString(getMod(this.attributeValue(attribute)));
|
||||
},
|
||||
|
||||
passiveAbility: function(attribute){
|
||||
var mod = +getMod(this.attributeValue(attribute));
|
||||
passiveAbility: function(charId, attribute){
|
||||
var mod = +getMod(Characters.calculate.attributeValue(charId, attribute));
|
||||
return 10 + mod;
|
||||
},
|
||||
|
||||
xpLevel: function(){
|
||||
var xp = this.experience();
|
||||
xpLevel: function(charId){
|
||||
var xp = Characters.calculate.experience(charId);
|
||||
for (var i = 0; i < 19; i++){
|
||||
if (xp < XP_TABLE[i]){
|
||||
return i;
|
||||
@@ -415,30 +424,103 @@ Characters.helpers({
|
||||
if (xp > 355000) return 20;
|
||||
return 0;
|
||||
},
|
||||
|
||||
level: function(){
|
||||
level: memoize(function(charId){
|
||||
var level = 0;
|
||||
Classes.find({charId: this._id}).forEach(function(cls){
|
||||
Classes.find({charId: charId}).forEach(function(cls){
|
||||
level += cls.level;
|
||||
});
|
||||
return level;
|
||||
},
|
||||
|
||||
experience: function(){
|
||||
}),
|
||||
experience: memoize(function(charId){
|
||||
var xp = 0;
|
||||
Experiences.find(
|
||||
{charId: this._id},
|
||||
{charId: charId},
|
||||
{fields: {value: 1}}
|
||||
).forEach(function(e){
|
||||
xp += e.value;
|
||||
});
|
||||
return xp;
|
||||
}),
|
||||
};
|
||||
|
||||
var depreciated = function() {
|
||||
//var err = new Error("this function has been depreciated");
|
||||
var name = "";
|
||||
if (Template.instance()){
|
||||
name = Template.instance().view.name;
|
||||
}
|
||||
var logString = "this function has been depreciated \n";
|
||||
if (name){
|
||||
logString += "View: " + name + "\n\n";
|
||||
}
|
||||
//logString += err.stack + "\n\n---------------------\n\n";
|
||||
console.log(logString);
|
||||
};
|
||||
|
||||
//functions and calculated values.
|
||||
//These functions can only rely on this._id since no other
|
||||
//field is likely to be attached to all returned characters
|
||||
Characters.helpers({
|
||||
//returns the value stored in the field requested
|
||||
//will set up dependencies on just that field
|
||||
getField : function(fieldName){
|
||||
depreciated();
|
||||
return Characters.calculate.getField(this._id, fieldName);
|
||||
},
|
||||
//returns the value of a field
|
||||
fieldValue : function(fieldName){
|
||||
depreciated();
|
||||
return Characters.calculate.fieldValue(this._id, fieldName);
|
||||
},
|
||||
attributeValue: function(attributeName){
|
||||
depreciated();
|
||||
return Characters.calculate.attributeValue(this._id, attributeName);
|
||||
},
|
||||
attributeBase: function(attributeName){
|
||||
depreciated();
|
||||
return Characters.calculate.attributeBase(this._id, attributeName);
|
||||
},
|
||||
skillMod: function(skillName){
|
||||
depreciated();
|
||||
return Characters.calculate.skillMod(this._id, skillName);
|
||||
},
|
||||
proficiency: function(skillName){
|
||||
depreciated();
|
||||
return Characters.calculate.proficiency(this._id, skillName);
|
||||
},
|
||||
passiveSkill: function(skillName){
|
||||
depreciated();
|
||||
return Characters.calculate.passiveSkill(this._id, skillName);
|
||||
},
|
||||
advantage: function(skillName){
|
||||
depreciated();
|
||||
return Characters.calculate.advantage(this._id, skillName);
|
||||
},
|
||||
abilityMod: function(attribute){
|
||||
depreciated();
|
||||
return Characters.calculate.abilityMod(this._id, attribute);
|
||||
},
|
||||
passiveAbility: function(attribute){
|
||||
depreciated();
|
||||
return Characters.calculate.passiveAbility(this._id, attribute);
|
||||
},
|
||||
xpLevel: function(){
|
||||
depreciated();
|
||||
return Characters.calculate.xpLevel(this._id);
|
||||
},
|
||||
level: function(){
|
||||
depreciated();
|
||||
return Characters.calculate.level(this._id);
|
||||
},
|
||||
experience: function(){
|
||||
depreciated();
|
||||
return Characters.calculate.experience(this._id);
|
||||
},
|
||||
});
|
||||
|
||||
//clean up all data related to that character before removing it
|
||||
Characters.after.remove(function(userId, character) {
|
||||
if (Meteor.isServer){
|
||||
if (Meteor.isServer){
|
||||
Characters.after.remove(function(userId, character) {
|
||||
Actions .remove({charId: character._id});
|
||||
Attacks .remove({charId: character._id});
|
||||
Buffs .remove({charId: character._id});
|
||||
@@ -451,8 +533,8 @@ Characters.after.remove(function(userId, character) {
|
||||
SpellLists .remove({charId: character._id});
|
||||
Items .remove({charId: character._id});
|
||||
Containers .remove({charId: character._id});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Characters.allow({
|
||||
insert: function(userId, doc) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Classes = new Mongo.Collection("classes");
|
||||
|
||||
Schemas.Class = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
name: {type: String, trim: false},
|
||||
level: {type: Number},
|
||||
createdAt: {
|
||||
|
||||
@@ -8,6 +8,7 @@ Schemas.Effect = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
@@ -107,6 +108,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");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Experiences = new Mongo.Collection("experience");
|
||||
|
||||
Schemas.Experience = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
name: {type: String, defaultValue: "New Experience", trim: false},
|
||||
description: {type: String, optional: true, trim: false},
|
||||
value: {type: Number, defaultValue: 0},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Features = new Mongo.Collection("features");
|
||||
|
||||
Schemas.Feature = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
name: {type: String, trim: false},
|
||||
description: {type: String, optional: true, trim: false},
|
||||
uses: {type: String, optional: true, trim: false},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Notes = new Mongo.Collection("notes");
|
||||
|
||||
Schemas.Note = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
name: {type: String, trim: false},
|
||||
description: {type: String, optional: true, trim: false},
|
||||
color: {
|
||||
|
||||
@@ -4,6 +4,7 @@ Schemas.Proficiency = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
@@ -30,7 +31,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);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
SpellLists = new Mongo.Collection("spellLists");
|
||||
|
||||
Schemas.SpellLists = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
name: {type: String, trim: false},
|
||||
description: {type: String, optional: true, trim: false},
|
||||
saveDC: {type: String, optional: true, trim: false},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Spells = new Mongo.Collection("spells");
|
||||
|
||||
Schemas.Spell = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
prepared: {
|
||||
type: String,
|
||||
defaultValue: "prepared",
|
||||
@@ -62,6 +62,23 @@ Spells.attachSchema(Schemas.Spell);
|
||||
|
||||
Spells.attachBehaviour("softRemovable");
|
||||
makeChild(Spells); //children of spell lists
|
||||
makeParent(Spells, ["name", "enabled"]); //parents of attacks
|
||||
|
||||
Spells.after.update(function (userId, spell, fieldNames) {
|
||||
//Update prepared state of spell and child attacks to be enabled or not
|
||||
if (_.contains(fieldNames, "prepared")) {
|
||||
var childAttacks = Attacks.find({"parent.id": spell._id}).fetch();
|
||||
if (spell.prepared === "unprepared") {
|
||||
_.each(childAttacks, function(attack){
|
||||
Attacks.update(attack._id, {$set: {enabled: false}});
|
||||
});
|
||||
} else if (spell.prepared === "prepared" || "always") {
|
||||
_.each(childAttacks, function(attack){
|
||||
Attacks.update(attack._id, {$set: {enabled: true}});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Spells.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
* Damage, healing and resource cost/recovery are all adjustments
|
||||
*/
|
||||
Schemas.Adjustment = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
//which stat the adjustment is applied to
|
||||
stat: {
|
||||
type: String,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
TemporaryHitPoints = new Mongo.Collection("temporaryHitPoints");
|
||||
|
||||
Schemas.TemporaryHitPoints = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
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() {
|
||||
|
||||
@@ -3,7 +3,7 @@ Containers = new Mongo.Collection("containers");
|
||||
|
||||
Schemas.Container = new SimpleSchema({
|
||||
name: {type: String, trim: false},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
isCarried: {type: Boolean},
|
||||
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
|
||||
@@ -4,7 +4,7 @@ Schemas.Item = new SimpleSchema({
|
||||
name: {type: String, defaultValue: "New Item", trim: false},
|
||||
plural: {type: String, optional: true, trim: false},
|
||||
description:{type: String, optional: true, trim: false},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id}, //id of owner
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, //id of owner
|
||||
quantity: {type: Number, min: 0, defaultValue: 1},
|
||||
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
|
||||
@@ -45,7 +45,26 @@ Meteor.methods({
|
||||
metaData: Object,
|
||||
});
|
||||
report.owner = this.userId;
|
||||
Reports.insert(report);
|
||||
var id = Reports.insert(report);
|
||||
var user = Meteor.users.findOne(this.userId);
|
||||
var sender = user &&
|
||||
user.emails &&
|
||||
user.emails[0] &&
|
||||
user.emails[0].address ||
|
||||
user.services &&
|
||||
user.services.google &&
|
||||
user.services.google.email ||
|
||||
"reports@dicecloud.com";
|
||||
var bodyText = "Report ID: " + id +
|
||||
"\nSeverity: " + report.severity +
|
||||
"\nType: " + report.type +
|
||||
"\n\n" + report.description;
|
||||
Email.send({
|
||||
from: sender,
|
||||
to: "stefan.zermatten@gmail.com",
|
||||
subject: "DiceCloud feedback - " + report.title,
|
||||
text: bodyText,
|
||||
});
|
||||
},
|
||||
deleteReport: function(id) {
|
||||
var user = Meteor.users.findOne(this.userId);
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
Router.configure({
|
||||
loadingTemplate: "loading",
|
||||
layoutTemplate: "layout",
|
||||
trackPageView: true,
|
||||
});
|
||||
|
||||
Router.plugin("ensureSignedIn", {
|
||||
except: [
|
||||
"home",
|
||||
"atSignIn",
|
||||
"atSignUp",
|
||||
"atForgotPassword",
|
||||
"atResetPwd",
|
||||
"atEnrollAccount",
|
||||
"atVerifyEmail",
|
||||
"atResendVerificationEmail",
|
||||
"loginButtons",
|
||||
"notFound",
|
||||
only: [
|
||||
"profile",
|
||||
"characterList",
|
||||
]
|
||||
});
|
||||
|
||||
@@ -31,23 +24,24 @@ Router.map(function() {
|
||||
this.route("characterList", {
|
||||
path: "/characterList",
|
||||
waitOn: function(){
|
||||
return Meteor.subscribe("characterList", Meteor.userId());
|
||||
return subsManager.subscribe("characterList", Meteor.userId());
|
||||
},
|
||||
data: {
|
||||
characters: function(){
|
||||
return Characters.find({}, {fields: {_id: 1}});
|
||||
return Characters.find({}, {fields: {_id: 1}, sort: {name: 1}});
|
||||
}
|
||||
},
|
||||
onAfterAction: function() {
|
||||
document.title = appName;
|
||||
},
|
||||
fastRender: true,
|
||||
});
|
||||
|
||||
this.route("characterSheet", {
|
||||
path: "/character/:_id",
|
||||
waitOn: function(){
|
||||
return [
|
||||
Meteor.subscribe("singleCharacter", this.params._id, Meteor.userId()),
|
||||
subsManager.subscribe("singleCharacter", this.params._id, Meteor.userId()),
|
||||
];
|
||||
},
|
||||
data: function() {
|
||||
@@ -64,6 +58,13 @@ Router.map(function() {
|
||||
document.title = name;
|
||||
}
|
||||
},
|
||||
//analytics
|
||||
trackPageView: false,
|
||||
onRun: function() {
|
||||
window.ga && window.ga("send", "pageview", "/character");
|
||||
this.next();
|
||||
},
|
||||
fastRender: true,
|
||||
});
|
||||
|
||||
this.route("loading", {
|
||||
@@ -81,7 +82,7 @@ Router.map(function() {
|
||||
name: "changeLog",
|
||||
waitOn: function() {
|
||||
return [
|
||||
Meteor.subscribe("changeLog"),
|
||||
subsManager.subscribe("changeLog"),
|
||||
]
|
||||
},
|
||||
data: {
|
||||
@@ -92,5 +93,13 @@ Router.map(function() {
|
||||
onAfterAction: function() {
|
||||
document.title = appName;
|
||||
},
|
||||
fastRender: true,
|
||||
});
|
||||
|
||||
this.route("/guide", {
|
||||
name: "guide",
|
||||
onAfterAction: function() {
|
||||
document.title = appName;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -20,6 +20,11 @@ openParentDialog = function(parent, charId, heroId) {
|
||||
template: "itemDialog",
|
||||
data: {itemId: parent.id},
|
||||
};
|
||||
} else if (parent.collection === "Spells") {
|
||||
detail = {
|
||||
template: "spellDialog",
|
||||
data: {spellId: parent.id},
|
||||
};
|
||||
}
|
||||
detail.heroId = heroId;
|
||||
detail.charId = charId;
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
Template.registerHelper("valueString", function(value) {
|
||||
var intValue = Math.round(value * 100);
|
||||
var cp = intValue % 10;
|
||||
intValue -= cp;
|
||||
cp = Math.round(cp);
|
||||
sp = intValue % 100;
|
||||
intValue -= sp;
|
||||
sp = Math.round(sp / 10)
|
||||
gp = Math.floor(value);
|
||||
|
||||
var resultArray = [];
|
||||
//sp
|
||||
var gp = Math.floor(value);
|
||||
if (gp > 0) {
|
||||
resultArray.push(gp + "gp");
|
||||
}
|
||||
//sp
|
||||
var sp = Math.floor(10 * (value % 1));
|
||||
if (sp > 0) {
|
||||
resultArray.push(sp + "sp");
|
||||
}
|
||||
//cp
|
||||
var cp = 10 * ((value * 10) % 1);
|
||||
cp = Math.round(cp * 1000) / 1000;
|
||||
if (cp > 0) {
|
||||
resultArray.push(cp + "cp");
|
||||
}
|
||||
|
||||
//build string with correct spacing
|
||||
var result = "";
|
||||
for (var i = 0; i < resultArray.length; i++) {
|
||||
for (var i = 0, l = resultArray.length; i < l; i++) {
|
||||
//add a space between values
|
||||
if (i !== 0) {
|
||||
result += " ";
|
||||
|
||||
@@ -3,17 +3,24 @@
|
||||
$thickColumnWidth: 304px;
|
||||
$thinColumnWidth: 240px;
|
||||
|
||||
//Column layouts of cards
|
||||
//Column layout
|
||||
.column-container {
|
||||
@include column-fill(balance);
|
||||
@include column-gap(8px);
|
||||
@include column-gap(0px);
|
||||
@include column-width($thickColumnWidth);
|
||||
padding: 8px;
|
||||
padding: 4px;
|
||||
|
||||
&.thin-columns {
|
||||
@include column-count(4);
|
||||
@include column-width($thinColumnWidth);
|
||||
}
|
||||
& > div {
|
||||
padding: 4px;
|
||||
//stop divs breaking over multiple columns
|
||||
-webkit-column-break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
//Cards
|
||||
@@ -21,20 +28,6 @@ $thinColumnWidth: 240px;
|
||||
background: white;
|
||||
border-radius: 2px;
|
||||
|
||||
.column-container & {
|
||||
margin-bottom: 8px;
|
||||
width: 100%;
|
||||
//hack to stop flickering
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transform: translateX(0);
|
||||
//stop breaking over column divide
|
||||
-webkit-column-break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
//Fixes extra margin at top of columns
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.top {
|
||||
cursor: pointer;
|
||||
padding: 16px;
|
||||
@@ -91,6 +84,6 @@ $thinColumnWidth: 240px;
|
||||
}
|
||||
|
||||
/* undo pointer cursor on detail box heading */
|
||||
#globalDetail .card .top {
|
||||
#globalDetail.card .top {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
background-color: #9E9E9E;
|
||||
}
|
||||
|
||||
.blue-grey {
|
||||
background-color: #607D8B;
|
||||
.app-grey {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
.white {
|
||||
|
||||
@@ -19,6 +19,21 @@ body {
|
||||
background-color: #E0E0E0;
|
||||
}
|
||||
|
||||
//fix tabs and core-toolbar having box shadow
|
||||
core-toolbar {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
//give drawer panel a shadow always
|
||||
core-header-panel[drawer] {
|
||||
box-shadow: 2px 0px 5px 0px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
//Paragraphs
|
||||
p {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
//Horizontal rule
|
||||
hr {
|
||||
background-color: #444;
|
||||
@@ -27,13 +42,13 @@ hr {
|
||||
color: #444;
|
||||
height: 1px;
|
||||
line-height: 0;
|
||||
margin: 16px -16px;
|
||||
margin: 16px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
//FABs
|
||||
.floatyButton {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
td {
|
||||
padding: 8px;
|
||||
&:nth-child(1) {
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.strengthTable{
|
||||
@@ -15,4 +12,10 @@ td {
|
||||
width: 250px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.summaryTable {
|
||||
&:nth-child(3){
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
<template name="characterSettings">
|
||||
{{#with character}}
|
||||
<div>
|
||||
<div layout horizontal>
|
||||
<div>Use variant encumbrance </div>
|
||||
<paper-toggle-button id="variantEncumbrance"
|
||||
checked={{settings.useVariantEncumbrance}}
|
||||
touch-action="pan-y">
|
||||
</paper-toggle-button>
|
||||
</div>
|
||||
<div style="height: 100px;">
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td>Hide Spells tab</td>
|
||||
<td>
|
||||
<paper-toggle-button id="hideSpellcasting"
|
||||
checked={{settings.hideSpellcasting}}
|
||||
touch-action="pan-y">
|
||||
</paper-toggle-button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Use variant encumbrance</td>
|
||||
<td>
|
||||
<paper-toggle-button id="variantEncumbrance"
|
||||
checked={{settings.useVariantEncumbrance}}
|
||||
touch-action="pan-y">
|
||||
</paper-toggle-button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{{/with}}
|
||||
<paper-button id="doneButton" affirmative> Done </paper-button>
|
||||
</template>
|
||||
|
||||
@@ -14,4 +14,13 @@ Template.characterSettings.events({
|
||||
);
|
||||
}
|
||||
},
|
||||
"change #hideSpellcasting": function(event, instance){
|
||||
var value = instance.find("#hideSpellcasting").checked;
|
||||
if (this.settings.hideSpellcasting !== value){
|
||||
Characters.update(
|
||||
this._id,
|
||||
{$set: {"settings.hideSpellcasting": value}}
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
<template name="shareDialog">
|
||||
<div style="width: 360px;">
|
||||
<div layout horizontal center>
|
||||
<div>Who can view this character: </div>
|
||||
<paper-dropdown-menu class="visibilityDropdown"
|
||||
label="Visibility">
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu visibilityMenu" selected={{viewPermission}}>
|
||||
<paper-item name="whitelist">Only people I share with</paper-item>
|
||||
<paper-item name="public">Anyone with link</paper-item>
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<div>
|
||||
{{#if readers.count}}
|
||||
<div style="font-weight: 500;">
|
||||
@@ -7,7 +19,7 @@
|
||||
</div>
|
||||
{{#each readers}}
|
||||
<div layout horizontal center>
|
||||
<div flex>{{username}}</div>
|
||||
<div flex>{{getUserName}}</div>
|
||||
<paper-icon-button class="deleteShare" icon="delete"></paper-icon-button>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
@@ -3,6 +3,10 @@ Template.shareDialog.onCreated(function(){
|
||||
});
|
||||
|
||||
Template.shareDialog.helpers({
|
||||
viewPermission: function() {
|
||||
var char = Characters.findOne(this._id, {fields: {settings: 1}});
|
||||
return char.settings.viewPermission || "whitelist";
|
||||
},
|
||||
readers: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {readers: 1}});
|
||||
return Meteor.users.find({_id: {$in: char.readers}});
|
||||
@@ -19,9 +23,20 @@ Template.shareDialog.helpers({
|
||||
return "User not found";
|
||||
}
|
||||
},
|
||||
getUserName: function() {
|
||||
return this.username || "user: " + this._id;
|
||||
}
|
||||
});
|
||||
|
||||
Template.shareDialog.events({
|
||||
"core-select .visibilityDropdown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
var char = Characters.findOne(this._id, {fields: {settings: 1}});
|
||||
if (value == char.settings.viewPermission) return;
|
||||
Characters.update(this._id, {$set: {"settings.viewPermission": value}});
|
||||
},
|
||||
"input #userNameOrEmailInput":
|
||||
function(event, instance){
|
||||
var userName = instance.find("#userNameOrEmailInput").value;
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
<paper-tab name="stats">Stats</paper-tab>
|
||||
<paper-tab name="features">Features</paper-tab>
|
||||
<paper-tab name="inventory">Inventory</paper-tab>
|
||||
{{#unless hideSpellcasting}}
|
||||
<paper-tab name="spells">Spells</paper-tab>
|
||||
{{/unless}}
|
||||
<paper-tab name="persona">Persona</paper-tab>
|
||||
<paper-tab name="journal">Journal</paper-tab>
|
||||
</paper-tabs>
|
||||
@@ -42,7 +44,9 @@
|
||||
<section flex name="stats">{{> stats}}</section>
|
||||
<section flex name="features">{{> features}}</section>
|
||||
<section flex name="inventory">{{> inventory}}</section>
|
||||
{{#unless hideSpellcasting}}
|
||||
<section flex name="spells">{{> spells}}</section>
|
||||
{{/unless}}
|
||||
<section flex name="persona">{{> persona}}</section>
|
||||
<section flex name="journal">{{> journal}}</section>
|
||||
</core-animated-pages>
|
||||
|
||||
@@ -17,6 +17,10 @@ Template.characterSheet.helpers({
|
||||
selectedTab: function(){
|
||||
return getTab(this._id);
|
||||
},
|
||||
hideSpellcasting: function() {
|
||||
var char = Characters.findOne(this._id);
|
||||
return char && char.settings.hideSpellcasting;
|
||||
},
|
||||
});
|
||||
|
||||
Template.characterSheet.events({
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
body /deep/ #statGroupDropDown {
|
||||
width: 120px;
|
||||
html /deep/ .operationDropDown {
|
||||
width: 152px;
|
||||
}
|
||||
|
||||
body /deep/ #statDropDown {
|
||||
width: 120px;
|
||||
html /deep/ .statDropDown {
|
||||
width: 152px;
|
||||
}
|
||||
|
||||
body /deep/ #operationDropDown {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
body /deep/ #damageMultiplierDropDown {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
body /deep/ #proficiencyDropDown {
|
||||
width: 120px;
|
||||
html /deep/ .damageMultiplierDropDown {
|
||||
width: 152px;
|
||||
}
|
||||
|
||||
html /deep/ .effectEdit paper-input {
|
||||
@@ -24,6 +16,7 @@ html /deep/ .effectEdit paper-input {
|
||||
}
|
||||
|
||||
html /deep/ .effectEdit {
|
||||
height: 64px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,23 @@
|
||||
<template name="effectEdit">
|
||||
<div class="effectEdit" layout horizontal center>
|
||||
<paper-dropdown-menu class="statGroupDropDown" label="Stat Group" flex>
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu statGroupMenu" selected={{selectedStatGroup}}>
|
||||
{{#each statGroups}}
|
||||
<paper-item class="statGroupSelect" name={{this}}>{{this}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{#if stats}}
|
||||
<paper-dropdown-menu class="statDropDown" label="Stat" flex>
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu statMenu" selected={{stat}} on-tap="onStatMenuTap">
|
||||
{{#each stats}}
|
||||
<paper-item name={{stat}}>{{name}}</paper-item>
|
||||
<paper-dropdown-menu class="statDropDown"
|
||||
label="Stat">
|
||||
<paper-dropdown layered
|
||||
class="dropdown">
|
||||
<core-menu class="menu statMenu" selected={{stat}}>
|
||||
{{#each statGroups}}
|
||||
<div style="font-weight: bold;
|
||||
margin-top: 16px;">{{this}}</div>
|
||||
{{#each stats}}
|
||||
<paper-item name={{stat}}>{{name}}</paper-item>
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{#if operations}}
|
||||
<paper-dropdown-menu class="operationDropDown" label="Operation" flex>
|
||||
<paper-dropdown-menu class="operationDropDown"
|
||||
label="Operation">
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu operationMenu" selected={{operation}}>
|
||||
{{#each operations}}
|
||||
@@ -31,24 +27,40 @@
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
{{> Template.dynamic template=effectValueTemplate}}
|
||||
<paper-icon-button class="deleteEffect" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
||||
{{#if effectValueTemplate}}
|
||||
{{> Template.dynamic template=effectValueTemplate}}
|
||||
{{else}}
|
||||
<div flex></div>
|
||||
{{/if}}
|
||||
<paper-icon-button class="deleteEffect"
|
||||
icon="delete">
|
||||
</paper-icon-button>
|
||||
<br>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="regularEffectValue">
|
||||
<paper-input class="effectValueInput" label="Value" floatinglabel value={{effectValue}} flex></paper-input>
|
||||
<paper-input class="effectValueInput"
|
||||
label="Value"
|
||||
floatinglabel
|
||||
value={{effectValue}}
|
||||
flex
|
||||
style="flex-basis: 100px;">
|
||||
</paper-input>
|
||||
</template>
|
||||
|
||||
<template name="multiplierEffectValue">
|
||||
<paper-dropdown-menu class="damageMultiplierDropDown" label="Damage Multiplier" flex>
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu class="menu multiplierMenu" selected={{value}}>
|
||||
<paper-dropdown-menu class="damageMultiplierDropDown"
|
||||
label="Damage Multiplier">
|
||||
<paper-dropdown layered
|
||||
class="dropdown">
|
||||
<core-menu class="menu multiplierMenu"
|
||||
selected={{value}}>
|
||||
<paper-item name="0.5">Resistance</paper-item>
|
||||
<paper-item name="2">Vulnerability</paper-item>
|
||||
<paper-item name="0">Immunity</paper-item>
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
<div flex></div>
|
||||
</template>
|
||||
|
||||
@@ -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"},
|
||||
@@ -93,24 +94,17 @@ var skillOperations = [
|
||||
{name: "Conditional Benefit", operation: "conditional"}
|
||||
];
|
||||
|
||||
Template.effectEdit.created = function(){
|
||||
var statGroup = statsDict[this.data.stat] && statsDict[this.data.stat].group;
|
||||
this.selectedStatGroup = new ReactiveVar(statGroup);
|
||||
};
|
||||
|
||||
Template.effectEdit.helpers({
|
||||
selectedStatGroup: function(){
|
||||
return Template.instance().selectedStatGroup.get();
|
||||
},
|
||||
statGroups: function(){
|
||||
return statGroupNames;
|
||||
},
|
||||
stats: function(){
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
var group = this;
|
||||
return statGroups[group];
|
||||
},
|
||||
operations: function(){
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
var stat = statsDict[this.stat];
|
||||
var group = stat && stat.group;
|
||||
if (group === "Weakness/Resistance") return null;
|
||||
if (group === "Saving Throws" || group === "Skills"){
|
||||
return skillOperations;
|
||||
@@ -120,7 +114,8 @@ Template.effectEdit.helpers({
|
||||
},
|
||||
effectValueTemplate: function(){
|
||||
//resistance/vulnerability template
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
var stat = statsDict[this.stat];
|
||||
var group = stat && stat.group;
|
||||
if (group === "Weakness/Resistance") return "multiplierEffectValue";
|
||||
|
||||
var op = this.operation;
|
||||
@@ -144,25 +139,6 @@ Template.effectEdit.events({
|
||||
Effects.softRemoveNode(this._id);
|
||||
GlobalUI.deletedToast(this._id, "Effects", "Effect");
|
||||
},
|
||||
"core-select .statGroupDropDown": function(event, instance){
|
||||
var detail = event.originalEvent.detail;
|
||||
if (!detail.isSelected) return;
|
||||
var groupName = detail.item.getAttribute("name");
|
||||
var oldName = Template.instance().selectedStatGroup.get();
|
||||
if (oldName != groupName){
|
||||
instance.selectedStatGroup.set(groupName);
|
||||
if (groupName === "Weakness/Resistance"){
|
||||
Effects.update(this._id, {$set: {
|
||||
value: 0.5,
|
||||
calculation: "",
|
||||
operation: "mul"}, $unset: {stat: ""}});
|
||||
} else {
|
||||
Effects.update(this._id,
|
||||
{$set: {operation: "add"},
|
||||
$unset: {stat: "", value: "", calculation: ""}});
|
||||
}
|
||||
}
|
||||
},
|
||||
"core-select .statDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if (!detail.isSelected) return;
|
||||
|
||||
@@ -42,6 +42,7 @@ var stats = {
|
||||
"rageDamage":{"name":"Rage Damage"},
|
||||
"expertiseDice":{"name":"Expertise Dice"},
|
||||
"superiorityDice":{"name":"Superiority Dice"},
|
||||
"carryMultiplier": {"name": "Carry Capacity Multiplier"},
|
||||
"level1SpellSlots":{"name":"level 1 Spell Slots"},
|
||||
"level2SpellSlots":{"name":"level 2 Spell Slots"},
|
||||
"level3SpellSlots":{"name":"level 3 Spell Slots"},
|
||||
@@ -57,40 +58,40 @@ var stats = {
|
||||
"d12HitDice":{"name":"d12 Hit Dice"},
|
||||
"acidMultiplier":{"name":"Acid damage", "group": "Weakness/Resistance"},
|
||||
"bludgeoningMultiplier":{
|
||||
"name":"Bludgeoning damage", "group": "Weakness/Resistance"
|
||||
"name":"Bludgeoning damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"coldMultiplier":{
|
||||
"name":"Cold damage", "group": "Weakness/Resistance"
|
||||
"name":"Cold damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"fireMultiplier":{
|
||||
"name":"Fire damage", "group": "Weakness/Resistance"
|
||||
"name":"Fire damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"forceMultiplier":{
|
||||
"name":"Force damage", "group": "Weakness/Resistance"
|
||||
"name":"Force damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"lightningMultiplier":{
|
||||
"name":"Lightning damage", "group": "Weakness/Resistance"
|
||||
"name":"Lightning damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"necroticMultiplier":{
|
||||
"name":"Necrotic damage", "group": "Weakness/Resistance"
|
||||
"name":"Necrotic damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"piercingMultiplier":{
|
||||
"name":"Piercing damage", "group": "Weakness/Resistance"
|
||||
"name":"Piercing damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"poisonMultiplier":{
|
||||
"name":"Poison damage", "group": "Weakness/Resistance"
|
||||
"name":"Poison damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"psychicMultiplier":{
|
||||
"name":"Psychic damage", "group": "Weakness/Resistance"
|
||||
"name":"Psychic damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"radiantMultiplier":{
|
||||
"name":"Radiant damage", "group": "Weakness/Resistance"
|
||||
"name":"Radiant damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"slashingMultiplier":{
|
||||
"name":"Slashing damage", "group": "Weakness/Resistance"
|
||||
"name":"Slashing damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
"thunderMultiplier":{
|
||||
"name":"Thunder damage", "group": "Weakness/Resistance"
|
||||
"name":"Thunder damage", "group": "Weakness/Resistance",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -110,8 +111,8 @@ var operations = {
|
||||
Template.effectView.helpers({
|
||||
sourceName: function(){
|
||||
var id = this.parent.id;
|
||||
if(!id) return;
|
||||
switch(this.parent.collection){
|
||||
if (!id) return;
|
||||
switch (this.parent.collection){
|
||||
case "Features":
|
||||
return "Feature - " + Features.findOne(id, {fields: {name: 1}}).name;
|
||||
case "Classes":
|
||||
@@ -130,33 +131,39 @@ Template.effectView.helpers({
|
||||
return stats[this.stat] && stats[this.stat].name || "No Stat";
|
||||
},
|
||||
operationName: function(){
|
||||
if(this.operation === "proficiency" ||
|
||||
if (this.operation === "proficiency" ||
|
||||
this.operation === "conditional") return null;
|
||||
if(stats[this.stat].group === "Weakness/Resistance") return null;
|
||||
if(this.operation === "add" && evaluateEffect(this.charId, this) < 0) return null;
|
||||
return operations[this.operation] && operations[this.operation].name || "No Operation";
|
||||
if (stats[this.stat] && stats[this.stat].group === "Weakness/Resistance")
|
||||
return null;
|
||||
if (this.operation === "add" && evaluateEffect(this.charId, this) < 0)
|
||||
return null;
|
||||
return operations[this.operation] &&
|
||||
operations[this.operation].name || "No Operation";
|
||||
},
|
||||
statValue: function(){
|
||||
if(this.operation === "advantage" ||
|
||||
if (this.operation === "advantage" ||
|
||||
this.operation === "disadvantage" ||
|
||||
this.operation === "fail"){
|
||||
return null;
|
||||
}
|
||||
if(this.operation === "proficiency"){
|
||||
if(this.value == 0.5 || this.calculation == 0.5) return "Half Proficiency";
|
||||
if(this.value == 1 || this.calculation == 1) return "Proficiency";
|
||||
if(this.value == 2 || this.calculation == 2) return "Double Proficiency";
|
||||
if (this.operation === "proficiency"){
|
||||
if (this.value == 0.5 || this.calculation == 0.5)
|
||||
return "Half Proficiency";
|
||||
if (this.value == 1 || this.calculation == 1)
|
||||
return "Proficiency";
|
||||
if (this.value == 2 || this.calculation == 2)
|
||||
return "Double Proficiency";
|
||||
}
|
||||
if(this.operation === "conditional"){
|
||||
if (this.operation === "conditional"){
|
||||
return this.calculation || this.value;
|
||||
}
|
||||
if(stats[this.stat].group === "Weakness/Resistance"){
|
||||
if(this.value === 0.5) return "Resistance";
|
||||
if(this.value === 2) return "Vulnerability";
|
||||
if(this.value === 0) return "Immunity";
|
||||
if (stats[this.stat] && stats[this.stat].group === "Weakness/Resistance"){
|
||||
if (this.value === 0.5) return "Resistance";
|
||||
if (this.value === 2) return "Vulnerability";
|
||||
if (this.value === 0) return "Immunity";
|
||||
}
|
||||
var value = evaluateEffect(this.charId, this);
|
||||
if(_.isNumber(value)) return value;
|
||||
if (_.isNumber(value)) return value;
|
||||
return this.calculation || this.value;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if description}}
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||
{{/if}}
|
||||
|
||||
{{> effectsViewList charId=charId parentId=_id}}
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
{{>resource name="sorceryPoints" title="Sorcery Points" color="teal" char=this}}
|
||||
<!--superiorityDice-->
|
||||
{{>resource name="superiorityDice" title="Superiority Dice" color="teal" char=this}}
|
||||
|
||||
|
||||
<!--Attacks-->
|
||||
<div>
|
||||
<paper-shadow class="card">
|
||||
<div class="top white">
|
||||
Attacks
|
||||
@@ -48,8 +49,10 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
|
||||
<!--Proficiencies-->
|
||||
<div>
|
||||
<paper-shadow class="card">
|
||||
<div class="white top">
|
||||
Proficiencies
|
||||
@@ -75,13 +78,15 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
|
||||
<!--features-->
|
||||
{{#each features}}
|
||||
<div>
|
||||
<paper-shadow class="card featureCard"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="top {{colorClass}} subhead"
|
||||
layout horizontal
|
||||
<div class="top {{colorClass}} subhead"
|
||||
layout horizontal
|
||||
hero-id="toolbar" {{detailHero}}>
|
||||
<div flex hero-id="title" {{detailHero}}>
|
||||
{{name}}
|
||||
@@ -94,57 +99,61 @@
|
||||
{{#if canEnable}}
|
||||
<core-tooltip label="Feature enabled"
|
||||
position="left">
|
||||
<paper-checkbox class="enabledCheckbox"
|
||||
checked={{enabled}}>
|
||||
<paper-checkbox class="enabledCheckbox"
|
||||
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>
|
||||
<paper-button class="useFeature"
|
||||
<paper-button class="useFeature"
|
||||
disabled={{noUsesLeft}}>
|
||||
Use
|
||||
</paper-button>
|
||||
<paper-button class="resetFeature"
|
||||
<paper-button class="resetFeature"
|
||||
disabled={{usesFull}}>
|
||||
Reset
|
||||
</paper-button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</paper-shadow>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="fab-buffer"></div>
|
||||
</div>
|
||||
{{#if canEditCharacter _id}}
|
||||
<paper-fab id="addFeature"
|
||||
class="floatyButton"
|
||||
icon="add"
|
||||
title="Add"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label="Add"
|
||||
<paper-fab id="addFeature"
|
||||
class="floatyButton"
|
||||
icon="add"
|
||||
title="Add"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label="Add"
|
||||
hero-id="main"></paper-fab>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="resource">
|
||||
{{#if char.attributeBase name}}
|
||||
<paper-shadow class="card"
|
||||
{{#if characterCalculate "attributeBase" char._id name}}
|
||||
<div>
|
||||
<paper-shadow class="card"
|
||||
hero-id="main" {{detailHero name char._id}}
|
||||
layout horizontal>
|
||||
<div class="left {{getColor}} display1 white-text"
|
||||
<div class="left {{getColor}} display1 white-text"
|
||||
hero-id="toolbar" {{detailHero name char._id}}
|
||||
layout horizontal center>
|
||||
<div style="margin-right: 8px;">
|
||||
<paper-icon-button class="resourceUp"
|
||||
icon="arrow-drop-up"
|
||||
<paper-icon-button class="resourceUp"
|
||||
icon="arrow-drop-up"
|
||||
disabled={{cantIncrement}}>
|
||||
</paper-icon-button>
|
||||
<paper-icon-button class="resourceDown"
|
||||
@@ -152,13 +161,14 @@
|
||||
disabled={{cantDecrement}}>
|
||||
</paper-icon-button>
|
||||
</div>
|
||||
<div>{{char.attributeValue name}}</div>
|
||||
<div>{{characterCalculate "attributeValue" char._id name}}</div>
|
||||
<!--<div>/{{char.attributeBase name}}</div>-->
|
||||
</div>
|
||||
<div class="right clickable"
|
||||
<div class="right clickable"
|
||||
flex layout horizontal center>
|
||||
{{title}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
@@ -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);
|
||||
@@ -96,16 +101,19 @@ Template.features.events({
|
||||
|
||||
Template.resource.helpers({
|
||||
cantIncrement: function(){
|
||||
var baseBigger = this.char.attributeValue(this.name) <
|
||||
this.char.attributeBase(this.name);
|
||||
return !baseBigger;
|
||||
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 || !canEditCharacter(this.char._id);
|
||||
},
|
||||
cantDecrement: function(){
|
||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
||||
return !valuePositive;
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
var valuePositive = value > 0;
|
||||
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";
|
||||
@@ -115,14 +123,17 @@ Template.resource.helpers({
|
||||
|
||||
Template.resource.events({
|
||||
"tap .resourceUp": function(event){
|
||||
if (this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||
if (value < base){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .resourceDown": function(event){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
if (value > 0){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
|
||||
@@ -13,8 +13,10 @@ var getFractionCarried = function(char) {
|
||||
weight += item.totalWeight();
|
||||
});
|
||||
//get strength
|
||||
var strength = char.attributeValue("strength");
|
||||
var capacity = strength * 15;
|
||||
var strength = Characters.calculate.attributeValue(char._id, "strength");
|
||||
var carryMultiplier = Characters.calculate
|
||||
.attributeValue(char._id, "carryMultiplier");
|
||||
var capacity = strength * 15 * carryMultiplier;
|
||||
return weight / capacity;
|
||||
};
|
||||
|
||||
@@ -22,7 +24,7 @@ Template.carryCapacityBar.onCreated(function() {
|
||||
var self = this;
|
||||
self.carriedFraction = new ReactiveVar(0);
|
||||
self.autorun(function() {
|
||||
self.carriedFraction.set(getFractionCarried(self.data));
|
||||
self.carriedFraction.set(getFractionCarried(Template.currentData()));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
<template name="containerView">
|
||||
<div layout horizontal wrap center justified>
|
||||
<table class="summaryTable fullwidth">
|
||||
<tr><td>Container</td><td>{{weight}}lbs</td><td>{{longValueString value}}</td></tr>
|
||||
<tr><td>Contents</td><td>{{contentsWeight}}lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
||||
<tr class="body2"><td>Total</td><td>{{totalWeight}}lbs</td><td>{{longValueString totalValue}}</td></tr>
|
||||
<tr><td>Container</td><td>{{round weight}}lbs</td><td>{{longValueString value}}</td></tr>
|
||||
<tr><td>Contents</td><td>{{round contentsWeight}}lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
||||
<tr class="body2"><td>Total</td><td>{{round totalWeight}}lbs</td><td>{{longValueString totalValue}}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
{{#if description}}
|
||||
<hr class="vertMargin">
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<div id="inventory" class="scroll-y" fit>
|
||||
<div class="column-container">
|
||||
<!--Net Worth-->
|
||||
<div>
|
||||
<paper-shadow class="card">
|
||||
<div class="white top" layout horizontal center>
|
||||
<div class="subhead" flex>
|
||||
@@ -13,7 +14,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
<!--Weight Carried-->
|
||||
<div>
|
||||
<paper-shadow class="card"
|
||||
hero-id="main" {{detailHero "weightCarried" _id}}>
|
||||
<div class="top green white-text weightCarried"
|
||||
@@ -35,8 +38,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">
|
||||
@@ -49,7 +51,9 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
</paper-shadow>
|
||||
</div>
|
||||
<!--Equipment-->
|
||||
<div>
|
||||
<paper-shadow class="card equipmentContainer">
|
||||
<div class="white top" layout horizontal center>
|
||||
<div class="subhead" flex>
|
||||
@@ -77,7 +81,9 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
<!--Carried Items-->
|
||||
<div>
|
||||
<paper-shadow class="card carriedContainer">
|
||||
<div class="white top" layout horizontal center>
|
||||
<div class="subhead" flex>
|
||||
@@ -96,8 +102,10 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
{{#each containers}}
|
||||
<paper-shadow class="card itemContainer"
|
||||
<div>
|
||||
<paper-shadow class="card itemContainer"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="top {{colorClass}}"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
@@ -114,6 +122,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>
|
||||
@@ -124,6 +133,7 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="fab-buffer"></div>
|
||||
@@ -152,11 +162,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 +176,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(){
|
||||
@@ -174,6 +180,20 @@ Template.inventory.events({
|
||||
heroId: itemId,
|
||||
});
|
||||
},
|
||||
"hold .inventoryItem": function(event, instance) {
|
||||
var itemId = this._id;
|
||||
var charId = Template.parentData()._id;
|
||||
var containerId = this.parent.id;
|
||||
GlobalUI.showDialog({
|
||||
template: "moveItemDialog",
|
||||
data: {
|
||||
charId: charId,
|
||||
itemId: itemId,
|
||||
containerId: containerId,
|
||||
},
|
||||
heading: "Move " + this.pluralName(),
|
||||
});
|
||||
},
|
||||
"tap .incrementButtons": function(event) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
html /deep/ .moveItemDialog paper-tabs::shadow #selectionBar {
|
||||
background-color: #D50000;
|
||||
}
|
||||
|
||||
html /deep/ .moveItemDialog paper-tab::shadow #ink {
|
||||
color: #D50000;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<template name="moveItemDialog">
|
||||
<div class="moveItemDialog">
|
||||
<paper-tabs selected="{{selectedTab}}">
|
||||
<paper-tab name="containers"
|
||||
class="clickable">
|
||||
Containers
|
||||
</paper-tab>
|
||||
<paper-tab name="characters"
|
||||
class="clickable">
|
||||
Characters
|
||||
</paper-tab>
|
||||
</paper-tabs>
|
||||
<core-animated-pages selected="{{selectedTab}}"
|
||||
transitions="slide-from-right"
|
||||
style="width: 250px;
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;">
|
||||
<section name="containers">
|
||||
<core-menu id="containerMenu" style="margin: 0;">
|
||||
{{#each containers}}
|
||||
<paper-item name={{_id}}
|
||||
layout horizontal center>
|
||||
<core-icon icon="image:brightness-1"
|
||||
style="color: {{hexColor color}};
|
||||
margin-right: 16px;">
|
||||
</core-icon>
|
||||
<div>{{name}}</div>
|
||||
</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</section>
|
||||
<section name="characters">
|
||||
<core-menu id="characterMenu" style="margin: 0;">
|
||||
{{#each characters}}
|
||||
<paper-item name={{_id}}
|
||||
layout horizontal center>
|
||||
<div class="item small">
|
||||
{{name}}
|
||||
</div>
|
||||
</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</section>
|
||||
</core-animated-pages>
|
||||
</div>
|
||||
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
|
||||
<paper-button id="moveButton" affirmative> Move </paper-button>
|
||||
</template>
|
||||
@@ -0,0 +1,56 @@
|
||||
Template.moveItemDialog.onCreated(function() {
|
||||
Session.setDefault("moveItemDialogTab", "containers");
|
||||
});
|
||||
|
||||
Template.moveItemDialog.helpers({
|
||||
selectedTab: function() {
|
||||
return Session.get("moveItemDialogTab");
|
||||
},
|
||||
characters: function() {
|
||||
var userId = Meteor.userId();
|
||||
return Characters.find(
|
||||
{
|
||||
$or: [
|
||||
{readers: userId},
|
||||
{writers: userId},
|
||||
{owner: userId},
|
||||
],
|
||||
_id: {$ne: this.charId},
|
||||
},
|
||||
{fields: {name: 1}}
|
||||
);
|
||||
},
|
||||
containers: function(){
|
||||
return Containers.find(
|
||||
{
|
||||
charId: this.charId,
|
||||
_id: {$ne: this.containerId},
|
||||
},
|
||||
{
|
||||
fields: {color: 1, name: 1},
|
||||
sort: {color: 1, name: 1},
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Template.moveItemDialog.events({
|
||||
"tap paper-tab": function(event) {
|
||||
Session.set("moveItemDialogTab", event.currentTarget.getAttribute("name"));
|
||||
},
|
||||
"tap #moveButton": function(event, instance) {
|
||||
var tab = Session.get("moveItemDialogTab");
|
||||
if (tab === "containers"){
|
||||
var containerId = instance.find("#containerMenu").selected;
|
||||
if (!containerId) throw "no menu selection";
|
||||
Meteor.call("moveItemToContainer", this.itemId, containerId);
|
||||
} else if (tab === "characters"){
|
||||
var characterId = instance.find("#characterMenu").selected;
|
||||
if (!characterId) throw "no menu selection";
|
||||
Meteor.call("moveItemToCharacter", this.itemId, characterId);
|
||||
} else {
|
||||
throw "Move item dialog tab is not set to containers or character," +
|
||||
" it is set to " + tab;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -6,23 +6,27 @@
|
||||
</div>
|
||||
{{#if description}}
|
||||
<hr class="vertMargin">
|
||||
<div class="pre-wrap">{{description}}</div>
|
||||
<div>{{#markdown}}{{description}}{{/markdown}}</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div horizontal layout>
|
||||
<!--Name-->
|
||||
<paper-input id="experienceNameInput" label="Name" floatinglabel value={{name}} flex></paper-input>
|
||||
<!--Value-->
|
||||
<paper-input-decorator label="Value" floatinglabel>
|
||||
<input id="valueInput" type="number" value={{value}}>
|
||||
</paper-input-decorator>
|
||||
</div>
|
||||
<!--Description-->
|
||||
<paper-input-decorator label="Description" floatinglabel layout vertical>
|
||||
<paper-autogrow-textarea>
|
||||
<textarea id="experienceDescriptionInput" placeholder value={{description}}></textarea>
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
{{> experienceEdit}}
|
||||
{{/baseDialog}}
|
||||
{{/with}}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template name="experienceEdit">
|
||||
<div horizontal layout>
|
||||
<!--Name-->
|
||||
<paper-input id="experienceNameInput" label="Name" floatinglabel value={{name}} flex></paper-input>
|
||||
<!--Value-->
|
||||
<paper-input-decorator label="Value" floatinglabel>
|
||||
<input id="valueInput" type="number" value={{value}}>
|
||||
</paper-input-decorator>
|
||||
</div>
|
||||
<!--Description-->
|
||||
<paper-input-decorator label="Description" floatinglabel layout vertical>
|
||||
<paper-autogrow-textarea>
|
||||
<textarea id="experienceDescriptionInput" placeholder value={{description}}></textarea>
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
</template>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Template.experienceEdit.onRendered(function(){
|
||||
updatePolymerInputs(this);
|
||||
});
|
||||
|
||||
Template.experienceDialog.helpers({
|
||||
experience: function(){
|
||||
Experiences.findOne(this.experienceId);
|
||||
@@ -18,8 +22,10 @@ Template.experienceDialog.events({
|
||||
);
|
||||
GlobalUI.closeDetail();
|
||||
},
|
||||
//TODO validate input (integer, non-negative, etc) for these inputs and give validation errors
|
||||
"change #experienceNameInput, input #experienceNameInput": function(event){
|
||||
});
|
||||
|
||||
Template.experienceEdit.events({
|
||||
"change #experienceNameInput": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
Experiences.update(this._id, {$set: {name: value}});
|
||||
},
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
<div id="journal" class="scroll-y" fit>
|
||||
<div class="column-container">
|
||||
<!--Experience Table-->
|
||||
<paper-shadow class="card experiencesCard"
|
||||
<div><paper-shadow class="card experiencesCard"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="top white subhead"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<div flex>Experience</div>
|
||||
<div >{{experience}} XP</div>
|
||||
<paper-icon-button class="black54" id="addXP" icon="add"></paper-icon-button>
|
||||
<div >{{characterCalculate "experience" _id}} XP</div>
|
||||
<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}}
|
||||
@@ -36,16 +37,16 @@
|
||||
</paper-button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</paper-shadow>
|
||||
</paper-shadow></div>
|
||||
<!--Class Table-->
|
||||
<paper-shadow class="card"
|
||||
<div><paper-shadow class="card"
|
||||
hero-id="main" {{detailHero}}>
|
||||
<div class="white top"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<div flex>
|
||||
<div class="containerName subhead">
|
||||
Level {{level}}
|
||||
Level {{characterCalculate "level" _id}}
|
||||
</div>
|
||||
{{#if nextLevelXP}}
|
||||
<div class="caption">
|
||||
@@ -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">
|
||||
@@ -76,29 +78,31 @@
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</paper-shadow></div>
|
||||
<!--Notes-->
|
||||
{{#each notes}}
|
||||
<div>
|
||||
<paper-shadow class="card" hero-id="main" {{detailHero}}>
|
||||
<div class="top {{colorClass}} noteTop subhead"
|
||||
hero-id="toolbar" {{detailHero}}
|
||||
layout horizontal center>
|
||||
{{name}}
|
||||
</div>
|
||||
<div class="bottom text">{{description}}</div>
|
||||
<div class="bottom">{{#markdown}}{{description}}{{/markdown}}</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="fab-buffer"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if canEditCharacter _id}}
|
||||
<paper-fab id="addNote"
|
||||
class="floatyButton"
|
||||
icon="add"
|
||||
title="Add"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
<paper-fab id="addNote"
|
||||
class="floatyButton"
|
||||
icon="add"
|
||||
title="Add"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
hero-id="main"></paper-fab>
|
||||
{{/if}}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -41,7 +41,7 @@ Template.journal.helpers({
|
||||
return Levels.find({charId: charId, classId: this._id}, {sort: {value: 1}});
|
||||
},
|
||||
nextLevelXP: function(){
|
||||
var currentLevel = this.level();
|
||||
var currentLevel = Characters.calculate.level(this._id);
|
||||
if (currentLevel < 20){
|
||||
return XP_TABLE[currentLevel];
|
||||
}
|
||||
|
||||
@@ -1,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}}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<template name="backgroundDialog">
|
||||
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true"}}
|
||||
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
|
||||
{{> proficiencyViewList charId=charId parentId=charId parentGroup="background"}}
|
||||
{{else}}
|
||||
{{> textDialogEdit}}
|
||||
{{> proficiencyEditList parentId=charId parentCollection="Characters" charId=charId parentGroup="background"}}
|
||||
{{/baseDialog}}
|
||||
</template>
|
||||
@@ -0,0 +1,8 @@
|
||||
Template.backgroundDialog.helpers({
|
||||
value: function(){
|
||||
var fieldSelector = {fields: {}};
|
||||
fieldSelector.fields[this.field] = 1;
|
||||
var char = Characters.findOne(this.charId, fieldSelector);
|
||||
return char[this.field];
|
||||
}
|
||||
});
|
||||
@@ -1,18 +1,36 @@
|
||||
<template name="personaDetailsDialog">
|
||||
{{#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,14 +3,45 @@
|
||||
<div id="persona" class="scroll-y" fit>
|
||||
<div class="column-container">
|
||||
{{#with characterDetails}}
|
||||
{{#containerCardHelper this}}{{alignment}} {{gender}} {{race}}{{/containerCardHelper}}
|
||||
<div>
|
||||
<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>
|
||||
</div>
|
||||
{{/with}}
|
||||
{{> containerCard characterField "description" "Description"}}
|
||||
{{> containerCard characterField "personality" "Personality Traits"}}
|
||||
{{> containerCard characterField "ideals" "Ideals"}}
|
||||
{{> containerCard characterField "bonds" "Bonds"}}
|
||||
{{> containerCard characterField "flaws" "Flaws"}}
|
||||
{{> containerCard characterField "backstory" "Background"}}
|
||||
<div>{{> containerCard characterField "description" "Description"}}</div>
|
||||
<div>{{> containerCard characterField "personality" "Personality Traits"}}</div>
|
||||
<div>{{> containerCard characterField "ideals" "Ideals"}}</div>
|
||||
<div>{{> containerCard characterField "bonds" "Bonds"}}</div>
|
||||
<div>{{> containerCard characterField "flaws" "Flaws"}}</div>
|
||||
<div>{{> containerCard characterField "backstory" "Background"}}</div>
|
||||
<div>
|
||||
<paper-shadow class="card">
|
||||
<div class="white top subhead">
|
||||
Languages
|
||||
@@ -21,6 +52,7 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,6 +72,6 @@
|
||||
{{title}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom text">{{> UI.contentBlock}}</div>
|
||||
<div class="bottom">{{#markdown}}{{> UI.contentBlock}}{{/markdown}}</div>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
</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,25 +40,28 @@ Template.persona.helpers({
|
||||
|
||||
Template.persona.events({
|
||||
"tap .characterField": function(event){
|
||||
if (this.field !== "details"){
|
||||
var charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "textDialog",
|
||||
data: {
|
||||
charId: charId,
|
||||
field: this.field,
|
||||
title: this.title,
|
||||
color: this.color,
|
||||
},
|
||||
heroId: this._id + this.field,
|
||||
});
|
||||
} else {
|
||||
if (this.field == "details"){
|
||||
this.charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "personaDetailsDialog",
|
||||
data: this,
|
||||
heroId: this._id + this.field,
|
||||
});
|
||||
} else {
|
||||
var template = "textDialog";
|
||||
if (this.field === "backstory") template = "backgroundDialog";
|
||||
var charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: template,
|
||||
data: {
|
||||
charId: charId,
|
||||
field: this.field,
|
||||
title: this.title,
|
||||
color: this.color,
|
||||
startEditing: true,
|
||||
},
|
||||
heroId: this._id + this.field,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template name="textDialog">
|
||||
{{#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}}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template name="proficiencyView">
|
||||
<div class="proficiencyView" layout horizontal center>
|
||||
<core-icon icon="{{profIcon}}"></core-icon>
|
||||
<div class="sideMargin">{{getName}}</div>
|
||||
<div class="proficiencyView item small"
|
||||
style="padding: 0;"
|
||||
layout horizontal center>
|
||||
<core-icon icon="{{profIcon}}" style="margin-right: 16px;"></core-icon>
|
||||
<div>{{getName}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{{#if proficiencies.count}}
|
||||
<hr class="vertMargin">
|
||||
<div class="proficiencies">
|
||||
<h2 class="spaceAfter">Proficiencies</h2>
|
||||
<h2 style="margin-bottom: 8px;">Proficiencies</h2>
|
||||
{{#each proficiencies}}
|
||||
{{> proficiencyView}}
|
||||
{{/each}}
|
||||
|
||||
@@ -9,24 +9,33 @@
|
||||
</template>
|
||||
|
||||
<template name="spellDetails">
|
||||
<div class="caption">
|
||||
<div class="body2">
|
||||
Level {{level}} {{school}}, {{preparedString}}
|
||||
</div>
|
||||
<div class="vertMargin">
|
||||
<div style="margin: 16px 0 16px 0;">
|
||||
{{#if castingTime}}
|
||||
<div>
|
||||
<span class="body2">Casting Time: </span><span>{{castingTime}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if range}}
|
||||
<div>
|
||||
<span class="body2">Range: </span><span>{{range}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if getComponents}}
|
||||
<div>
|
||||
<span class="body2">Components: </span><span>{{getComponents}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if duration}}
|
||||
<div>
|
||||
<span class="body2">Duration: </span><span>{{duration}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||
{{> attacksViewList charId=charId parentId=_id}}
|
||||
</template>
|
||||
|
||||
<template name="spellEdit">
|
||||
@@ -126,4 +135,5 @@
|
||||
<textarea id="descriptionInput" placeholder value={{description}}></textarea>
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
{{> attackEditList parentId=_id parentCollection="Spells" charId=charId enabled=true name=name}}
|
||||
</template>
|
||||
@@ -20,7 +20,7 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
<hr class="vertMargin">
|
||||
<div class="pre-wrap">{{evaluateString charId description}}</div>
|
||||
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<!--Name-->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template name="spells">
|
||||
<div fit>
|
||||
<div id="spells" class="scroll-y" fit>
|
||||
<div style="padding: 4px;"
|
||||
<div style="padding: 4px;"
|
||||
layout horizontal start wrap>
|
||||
{{#if hasSlots}}
|
||||
<paper-shadow class="card"
|
||||
@@ -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>
|
||||
@@ -91,7 +92,7 @@
|
||||
<div class="tall spell item"
|
||||
hero-id="main" {{detailHero}}
|
||||
layout horizontal center>
|
||||
<core-icon icon="social:whatshot"
|
||||
<core-icon icon="social:whatshot"
|
||||
style="color: {{hexColor color}};
|
||||
margin-right: 16px;"
|
||||
></core-icon>
|
||||
@@ -143,4 +144,4 @@
|
||||
</core-tooltip>
|
||||
{{/fabMenu}}
|
||||
{{/if}}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -84,39 +84,35 @@ Template.spells.helpers({
|
||||
},
|
||||
cantCast: function(level, char){
|
||||
for (var i = level; i <= 9; i++){
|
||||
if (char.attributeValue("level" + i + "SpellSlots") > 0){
|
||||
if (Characters.calculate.attributeValue(char._id, "level" + i + "SpellSlots") > 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
baseSlots: function(char){
|
||||
return char.attributeBase("level" + this.level + "SpellSlots");
|
||||
},
|
||||
slots: function(char){
|
||||
return char.attributeValue("level" + this.level + "SpellSlots");
|
||||
},
|
||||
showSlots: function(char){
|
||||
return this.level && char.attributeBase("level" + this.level + "SpellSlots");
|
||||
return this.level && Characters.calculate.attributeBase(
|
||||
char._id, "level" + this.level + "SpellSlots"
|
||||
);
|
||||
},
|
||||
hasSlots: function(){
|
||||
for (var i = 1; i <= 9; i += 1){
|
||||
if (this.attributeBase("level" + i + "SpellSlots")){
|
||||
if (Characters.calculate.attributeBase(this._id, "level" + i + "SpellSlots")){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
slotBubbles: function(char){
|
||||
var baseSlots = char.attributeBase("level" + this.level + "SpellSlots");
|
||||
var currentSlots = char.attributeValue("level" + this.level + "SpellSlots");
|
||||
var baseSlots = Characters.calculate.attributeBase(char._id, "level" + this.level + "SpellSlots");
|
||||
var currentSlots = Characters.calculate.attributeValue(char._id, "level" + this.level + "SpellSlots");
|
||||
var slotsUsed = baseSlots - currentSlots;
|
||||
var bubbles = [];
|
||||
var i;
|
||||
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,
|
||||
});
|
||||
@@ -124,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,
|
||||
});
|
||||
@@ -143,15 +139,15 @@ Template.spells.events({
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (event.currentTarget.icon === "radio-button-off"){
|
||||
if (
|
||||
char.attributeValue(this.attribute) <
|
||||
char.attributeBase(this.attribute)
|
||||
Characters.calculate.attributeValue(char._id, this.attribute) <
|
||||
Characters.calculate.attributeBase(char._id, this.attribute)
|
||||
){
|
||||
modifier = {$inc: {}};
|
||||
modifier.$inc[this.attribute + ".adjustment"] = 1;
|
||||
Characters.update(this.charId, modifier, {validate: false});
|
||||
}
|
||||
} else {
|
||||
if (char.attributeValue(this.attribute) > 0){
|
||||
if (Characters.calculate.attributeValue(char._id, this.attribute) > 0){
|
||||
modifier = {$inc: {}};
|
||||
modifier.$inc[this.attribute + ".adjustment"] = -1;
|
||||
Characters.update(this.charId, modifier, {validate: false});
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<template name="abilityMiniCard">
|
||||
<paper-shadow class="card abilityMiniCard clickable"
|
||||
<div>
|
||||
<paper-shadow class="card abilityMiniCard clickable"
|
||||
hero-id="main" {{detailHero ability ../_id}}
|
||||
layout horizontal>
|
||||
<div class="left white-text {{color}}"
|
||||
hero-id="toolbar" {{detailHero ability ../_id}}>
|
||||
<div class="display1">{{../attributeValue ability}}</div>
|
||||
<div class="title">{{../abilityMod ability}}</div>
|
||||
<div class="display1">{{characterCalculate "attributeValue" ../_id ability}}</div>
|
||||
<div class="title">{{abilityMod}}</div>
|
||||
</div>
|
||||
<div class="right subhead" layout horizontal center>
|
||||
{{title}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Template.abilityMiniCard.helpers({
|
||||
abilityMod: function() {
|
||||
return signedString(
|
||||
Characters.calculate.abilityMod(
|
||||
Template.parentData()._id, this.ability
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -106,10 +106,8 @@ Template.attributeDialogView.helpers({
|
||||
return a || b || c;
|
||||
},
|
||||
adjustment: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
var value = char.attributeValue(this.statName);
|
||||
var base = char.attributeBase(this.statName);
|
||||
var value = Characters.calculate.attributeValue(this.charId, this.statName);
|
||||
var base = Characters.calculate.attributeBase(this.charId, this.statName);
|
||||
return value - base;
|
||||
},
|
||||
baseEffects: function(){
|
||||
@@ -138,14 +136,10 @@ Template.attributeDialogView.helpers({
|
||||
);
|
||||
},
|
||||
attributeBase: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) throw "character is " + char;
|
||||
return char.attributeBase(this.statName);
|
||||
return Characters.calculate.attributeBase(this.charId, this.statName);
|
||||
},
|
||||
attributeValue: function() {
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) throw "character is " + char;
|
||||
return char.attributeValue(this.statName);
|
||||
return Characters.calculate.attributeValue(this.charId, this.statName);
|
||||
},
|
||||
sourceName: function(){
|
||||
if (this.parent.group === "racial"){
|
||||
|
||||
@@ -2,27 +2,27 @@
|
||||
<table class="carryCapacityTable strengthTable">
|
||||
<tr>
|
||||
<td>Encumbered</td>
|
||||
<td>>{{evaluate charId "strength * 5"}}lbs</td>
|
||||
<td>>{{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>>{{evaluate charId "strength * 10"}}lbs</td>
|
||||
<td>>{{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>>{{evaluate charId "strength * 15"}}lbs</td>
|
||||
<td>>{{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>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.healthCard paper-slider{
|
||||
.healthCard paper-diff-slider{
|
||||
width: 100%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
@@ -1,43 +1,60 @@
|
||||
<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>
|
||||
<paper-slider id="hitPointSlider"
|
||||
value={{attributeValue "hitPoints"}}
|
||||
max={{attributeBase "hitPoints"}}
|
||||
editable pin
|
||||
role="slider"
|
||||
></paper-slider>
|
||||
<paper-diff-slider id="hitPointSlider"
|
||||
value={{characterCalculate "attributeValue" _id "hitPoints"}}
|
||||
max={{characterCalculate "attributeBase" _id "hitPoints"}}
|
||||
editable pin
|
||||
disabled={{#unless canEditCharacter _id}}true{{/unless}}
|
||||
role="slider">
|
||||
</paper-diff-slider>
|
||||
</div>
|
||||
{{#each tempHitPoints}}
|
||||
<div>
|
||||
{{name}}
|
||||
<div layout horizontal>
|
||||
<paper-slider class="tempHitPointSlider"
|
||||
<paper-diff-slider class="tempHitPointSlider"
|
||||
value={{left}}
|
||||
max={{maximum}}
|
||||
editable pin
|
||||
role="slider"
|
||||
flex
|
||||
></paper-slider>
|
||||
{{#unless left}}{{#unless deleteOnZero}}
|
||||
></paper-diff-slider>
|
||||
{{#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}} <div>Immune: {{#each multipliers.immunities}} {{name}} {{/each}}</div>{{/if}}
|
||||
{{#if multipliers.resistances.length}}<div>Resistance: {{#each multipliers.resistances}} {{name}} {{/each}}</div>{{/if}}
|
||||
{{#if multipliers.weaknesses.length}} <div>Weakness: {{#each multipliers.weaknesses}} {{name}} {{/each}}</div>{{/if}}
|
||||
{{#if multipliers.immunities.length}}
|
||||
<div>
|
||||
Immune: {{#each multipliers.immunities}} {{name}} {{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if multipliers.resistances.length}}
|
||||
<div>
|
||||
Resistance: {{#each multipliers.resistances}} {{name}} {{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if multipliers.weaknesses.length}}
|
||||
<div>
|
||||
Weakness: {{#each multipliers.weaknesses}} {{name}} {{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if showDeathSave}}
|
||||
{{#with deathSaveObject}}
|
||||
|
||||
@@ -3,7 +3,7 @@ Template.healthCard.helpers({
|
||||
return TemporaryHitPoints.find({charId: this._id});
|
||||
},
|
||||
showDeathSave: function(){
|
||||
return this.attributeValue("hitPoints") <= 0;
|
||||
return Characters.calculate.attributeValue(this._id, "hitPoints") <= 0;
|
||||
},
|
||||
deathSaveObject: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {deathSave: 1}});
|
||||
@@ -27,21 +27,20 @@ Template.healthCard.helpers({
|
||||
return this.fail >= 3;
|
||||
},
|
||||
multipliers: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {_id: 1}});
|
||||
var multipliers = [
|
||||
{name: "Acid", value: char.attributeValue("acidMultiplier", 1)},
|
||||
{name: "Bludgeoning", value: char.attributeValue("bludgeoningMultiplier", 1)},
|
||||
{name: "Cold", value: char.attributeValue("coldMultiplier", 1)},
|
||||
{name: "Fire", value: char.attributeValue("fireMultiplier", 1)},
|
||||
{name: "Force", value: char.attributeValue("forceMultiplier", 1)},
|
||||
{name: "Lightning", value: char.attributeValue("lightningMultiplier", 1)},
|
||||
{name: "Necrotic", value: char.attributeValue("necroticMultiplier", 1)},
|
||||
{name: "Piercing", value: char.attributeValue("piercingMultiplier", 1)},
|
||||
{name: "Poison", value: char.attributeValue("poisonMultiplier", 1)},
|
||||
{name: "Psychic", value: char.attributeValue("psychicMultiplier", 1)},
|
||||
{name: "Radiant", value: char.attributeValue("radiantMultiplier", 1)},
|
||||
{name: "Slashing", value: char.attributeValue("slashingMultiplier", 1)},
|
||||
{name: "Thunder", value: char.attributeValue("thunderMultiplier", 1)},
|
||||
{name: "Acid", value: Characters.calculate.attributeValue(this._id, "acidMultiplier")},
|
||||
{name: "Bludgeoning", value: Characters.calculate.attributeValue(this._id, "bludgeoningMultiplier")},
|
||||
{name: "Cold", value: Characters.calculate.attributeValue(this._id, "coldMultiplier")},
|
||||
{name: "Fire", value: Characters.calculate.attributeValue(this._id, "fireMultiplier")},
|
||||
{name: "Force", value: Characters.calculate.attributeValue(this._id, "forceMultiplier")},
|
||||
{name: "Lightning", value: Characters.calculate.attributeValue(this._id, "lightningMultiplier")},
|
||||
{name: "Necrotic", value: Characters.calculate.attributeValue(this._id, "necroticMultiplier")},
|
||||
{name: "Piercing", value: Characters.calculate.attributeValue(this._id, "piercingMultiplier")},
|
||||
{name: "Poison", value: Characters.calculate.attributeValue(this._id, "poisonMultiplier")},
|
||||
{name: "Psychic", value: Characters.calculate.attributeValue(this._id, "psychicMultiplier")},
|
||||
{name: "Radiant", value: Characters.calculate.attributeValue(this._id, "radiantMultiplier")},
|
||||
{name: "Slashing", value: Characters.calculate.attributeValue(this._id, "slashingMultiplier")},
|
||||
{name: "Thunder", value: Characters.calculate.attributeValue(this._id, "thunderMultiplier")},
|
||||
];
|
||||
multipliers = _.groupBy(multipliers, "value");
|
||||
return {
|
||||
@@ -55,7 +54,8 @@ Template.healthCard.helpers({
|
||||
Template.healthCard.events({
|
||||
"change #hitPointSlider": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
var adjustment = value - this.attributeBase("hitPoints");
|
||||
var base = Characters.calculate.attributeBase(this._id, "hitPoints")
|
||||
var adjustment = value - base;
|
||||
Characters.update(this._id, {$set: {"hitPoints.adjustment": adjustment}});
|
||||
//reset the death saves if we are gaining HP
|
||||
if (value > 0)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<template name="hitDice">
|
||||
{{#if ../attributeBase name}}
|
||||
<paper-shadow class="card hit-dice" hero-id="main"
|
||||
{{detailHero name ../_id}}
|
||||
{{#if characterCalculate "attributeBase" ../_id name}}
|
||||
<div>
|
||||
<paper-shadow class="card hit-dice" hero-id="main"
|
||||
{{detailHero name ../_id}}
|
||||
layout horizontal>
|
||||
<div class="left green display1 white-text"
|
||||
<div class="left green display1 white-text"
|
||||
hero-id="toolbar" {{detailHero name ../_id}}
|
||||
layout horizontal>
|
||||
<div>
|
||||
<paper-icon-button class="resourceUp"
|
||||
icon="arrow-drop-up"
|
||||
<paper-icon-button class="resourceUp"
|
||||
icon="arrow-drop-up"
|
||||
disabled={{cantIncrement}}>
|
||||
</paper-icon-button>
|
||||
<paper-icon-button class="resourceDown"
|
||||
@@ -18,10 +19,10 @@
|
||||
</div>
|
||||
<div class="resourceValue" layout vertical center>
|
||||
<div>
|
||||
{{../attributeValue name}}
|
||||
{{characterCalculate "attributeValue" ../_id name}}
|
||||
</div>
|
||||
<div class="title white-text">
|
||||
d{{diceNum}} {{../abilityMod "constitution"}}
|
||||
d{{diceNum}} {{conMod}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,5 +30,6 @@
|
||||
Hit Dice
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
Template.hitDice.helpers({
|
||||
cantIncrement: function(){
|
||||
var valueSmallerThanBase = this.char.attributeValue(this.name) <
|
||||
this.char.attributeBase(this.name);
|
||||
return !valueSmallerThanBase;
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||
return value >= base || !canEditCharacter(this.char._id);
|
||||
},
|
||||
cantDecrement: function(){
|
||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
||||
return !valuePositive;
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
return value <= 0 || !canEditCharacter(this.char._id);
|
||||
},
|
||||
conMod: function(){
|
||||
return signedString(
|
||||
Characters.calculate.abilityMod(this.char._id, "constitution")
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Template.hitDice.events({
|
||||
"tap .resourceUp": function(event){
|
||||
if (this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||
if (value < base){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .resourceDown": function(event){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||
if (value > 0){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- needs name, char, and skillName -->
|
||||
<!-- needs name, charId, and skillName -->
|
||||
<template name="skillDialog">
|
||||
{{#baseDialog title=name class=color hideEdit=true}}
|
||||
{{> skillDialogView}}
|
||||
@@ -8,7 +8,7 @@
|
||||
<template name="skillDialogView">
|
||||
<div layout vertical center>
|
||||
<div class="display2">
|
||||
{{char.skillMod skillName}}
|
||||
{{characterCalculate "skillMod" charId skillName}}
|
||||
</div>
|
||||
<div class="subhead">
|
||||
<core-icon icon="{{profIcon}}" class="black54"></core-icon>
|
||||
@@ -25,9 +25,9 @@
|
||||
<table class="summaryTable">
|
||||
<tr>
|
||||
<td>{{abilityName}}</td>
|
||||
<td>{{char.abilityMod ability}}</td>
|
||||
<td>{{characterCalculate "abilityMod" charId ability}}</td>
|
||||
</tr>
|
||||
{{#if char.proficiency skillName}}
|
||||
{{#if characterCalculate "proficiency" charId skillName}}
|
||||
<tr>
|
||||
<td>{{proficiencyValue}}</td>
|
||||
<td>{{signedString profBonus}}</td>
|
||||
@@ -59,7 +59,7 @@
|
||||
{{/each}}
|
||||
<tr class="body2">
|
||||
<td>Total</td>
|
||||
<td>{{char.skillMod skillName}}</td>
|
||||
<td>{{characterCalculate "skillMod" charId skillName}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -106,9 +106,7 @@ Template.skillDialogView.helpers({
|
||||
return a || b || c;
|
||||
},
|
||||
profIcon: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
var prof = char.proficiency(this.skillName);
|
||||
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if (prof === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
@@ -123,13 +121,13 @@ Template.skillDialogView.helpers({
|
||||
profBonus: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
return char.proficiency(this.skillName) *
|
||||
char.attributeValue("proficiencyBonus");
|
||||
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||
var proficiencyBonus =
|
||||
Characters.calculate.attributeValue(this.charId, "proficiencyBonus");
|
||||
return prof * proficiencyBonus;
|
||||
},
|
||||
proficiencyValue: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if (!char) return;
|
||||
var prof = char.proficiency(this.skillName);
|
||||
var prof = Characters.calculate.proficiency(this.charId, this.skillName);
|
||||
if (prof == 0.5) return "Half Proficiency";
|
||||
if (prof == 1) return "Proficient";
|
||||
if (prof == 2) return "Double Proficiency";
|
||||
@@ -199,20 +197,21 @@ Template.skillDialogView.helpers({
|
||||
return skill.ability;
|
||||
},
|
||||
abilityName: function(){
|
||||
var opts = {fields: {}};
|
||||
opts.fields[this.skillName] = 1;
|
||||
var char = Characters.findOne(this.charId, opts);
|
||||
if (!char) return;
|
||||
var skill = char[this.skillName];
|
||||
var skill = Characters.calculate.getField(this.charId, this.skillName);
|
||||
if (!skill) return;
|
||||
var ability = skill.ability;
|
||||
return abilities[ability] && abilities[ability].name;
|
||||
},
|
||||
char: function(){
|
||||
return Characters.findOne(this.charId, {fields:{_id: 1}});
|
||||
},
|
||||
sourceName: function(){
|
||||
if (this.parent.collection === "Characters") return "inate";
|
||||
if (this.parent.collection === "Characters"){
|
||||
if (this.parent.group === "racial"){
|
||||
return Characters.calculate.getField(this.charId, "race") || "Race";
|
||||
}
|
||||
if (this.parent.group === "background"){
|
||||
return "Background";
|
||||
}
|
||||
return "Innate";
|
||||
}
|
||||
return this.getParent().name;
|
||||
},
|
||||
operationName: function(){
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
{{#if failSkill}}
|
||||
<div class="fail skill-mod">fail</div>
|
||||
{{else}}
|
||||
<div class="{{advantage}} skill-mod">{{../skillMod skill}}</div>
|
||||
<div class="{{advantage}} skill-mod">
|
||||
{{skillMod}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div flex>
|
||||
{{name}}
|
||||
@@ -16,7 +18,7 @@
|
||||
*
|
||||
{{/if}}
|
||||
{{#if showPassive}}
|
||||
({{../passiveSkill skill}})
|
||||
({{characterCalculate "passiveSkill" ../_id skill}})
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
Template.skillRow.helpers({
|
||||
skillMod: function() {
|
||||
return signedString(
|
||||
Characters.calculate.skillMod(
|
||||
Template.parentData()._id, this.skill
|
||||
)
|
||||
);
|
||||
},
|
||||
profIcon: function(){
|
||||
var prof = Template.parentData(1).proficiency(this.skill);
|
||||
var charId = Template.parentData()._id;
|
||||
var prof = Characters.calculate.proficiency(charId, this.skill);
|
||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if (prof === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
return "radio-button-off";
|
||||
},
|
||||
failSkill: function(){
|
||||
var charId = Template.parentData(1)._id;
|
||||
var charId = Template.parentData()._id;
|
||||
return Effects.find({
|
||||
charId: charId,
|
||||
stat: this.skill,
|
||||
@@ -16,12 +24,13 @@ Template.skillRow.helpers({
|
||||
}).count();
|
||||
},
|
||||
advantage: function(){
|
||||
var advantage = Template.parentData(1).advantage(this.skill);
|
||||
var charId = Template.parentData()._id;
|
||||
var advantage = Characters.calculate.advantage(charId, this.skill);
|
||||
if (advantage > 0) return "advantage";
|
||||
if (advantage < 0) return "disadvantage";
|
||||
},
|
||||
conditionalCount: function(){
|
||||
var charId = Template.parentData(1)._id;
|
||||
var charId = Template.parentData()._id;
|
||||
return Effects.find({
|
||||
charId: charId,
|
||||
stat: this.skill,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
{{>hitDice name="d10HitDice" diceNum="10" char=this}}
|
||||
{{>hitDice name="d12HitDice" diceNum="12" char=this}}
|
||||
<!--Saving Throws-->
|
||||
<div>
|
||||
<paper-shadow class="card">
|
||||
<div class="top white subhead">
|
||||
Saving Throws
|
||||
@@ -40,7 +41,9 @@
|
||||
{{> skillRow name="Charisma" skill="charismaSave"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
<!--Skills-->
|
||||
<div>
|
||||
<paper-shadow class="card">
|
||||
<div class="top white subhead">
|
||||
Skills
|
||||
@@ -66,22 +69,25 @@
|
||||
{{> skillRow name="Survival" skill="survival"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="statCard">
|
||||
<div>
|
||||
<paper-shadow class="card statCard clickable" hero-id="main" {{detailHero stat ../_id}} layout horizontal>
|
||||
<div class="left display1 white-text {{color}}"
|
||||
hero-id="toolbar" {{detailHero stat ../_id}}>
|
||||
{{#if isSkill}}
|
||||
{{../skillMod stat}}
|
||||
{{prefix}}{{skillMod}}
|
||||
{{else}}
|
||||
{{prefix}}{{../attributeValue stat}}
|
||||
{{prefix}}{{characterCalculate "attributeValue" ../_id stat}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="right subhead" flex horizontal layout center>
|
||||
{{name}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -67,6 +67,12 @@ Template.stats.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.stats.helpers({
|
||||
|
||||
Template.statCard.helpers({
|
||||
skillMod: function() {
|
||||
return signedString(
|
||||
Characters.calculate.skillMod(
|
||||
Template.parentData()._id, this.stat
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template name="characterList">
|
||||
<core-toolbar class="blue-grey white-text">
|
||||
<core-toolbar class="app-grey white-text">
|
||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||
<div flex>
|
||||
Characters
|
||||
|
||||
@@ -13,7 +13,10 @@ Template.characterSideList.helpers({
|
||||
{owner: userId},
|
||||
]
|
||||
},
|
||||
{fields: {name: 1}}
|
||||
{
|
||||
fields: {name: 1},
|
||||
sort: {name: 1},
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
</paper-autogrow-textarea>
|
||||
</paper-input-decorator>
|
||||
</div>
|
||||
<paper-button id="cancelButton" affirmative>Cancel</paper-button>
|
||||
<paper-button id="sendButton" affirmative>Send </paper-button>
|
||||
<paper-button id="cancelButton"
|
||||
affirmative>
|
||||
Cancel
|
||||
</paper-button>
|
||||
<paper-button id="sendButton"
|
||||
affirmative
|
||||
disabled={{invalid}}>
|
||||
Send
|
||||
</paper-button>
|
||||
</template>
|
||||
@@ -1,4 +1,23 @@
|
||||
Template.feedback.onCreated(function() {
|
||||
this.title = new ReactiveVar("");
|
||||
this.description = new ReactiveVar("");
|
||||
});
|
||||
|
||||
Template.feedback.helpers({
|
||||
invalid: function() {
|
||||
var inst = Template.instance();
|
||||
return !inst.title.get() ||
|
||||
!inst.description.get();
|
||||
}
|
||||
});
|
||||
|
||||
Template.feedback.events({
|
||||
"input #feedbackTitle": function(event, instance) {
|
||||
instance.title.set(instance.find("#feedbackTitle").value);
|
||||
},
|
||||
"input #feedbackDescription": function(event, instance) {
|
||||
instance.description.set(instance.find("#feedbackDescription").value);
|
||||
},
|
||||
"tap #sendButton": function(event, instance) {
|
||||
var report = {};
|
||||
report.title = instance.find("#feedbackTitle").value;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template name="guide">
|
||||
<core-toolbar class="app-grey white-text">
|
||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||
<div flex>Guide</div>
|
||||
</core-toolbar>
|
||||
<div layout vertical center>
|
||||
<paper-shadow class="wallOfText card" style="padding: 32px; max-width: 800px;">
|
||||
<h1>Dicecloud Beta</h1>
|
||||
<p>Welcome to the Dicecloud beta. Please don't share the link with people you don't actively play with, since the beta is intended to be small, and your experience will probably get laggy if it gets more traffic than I'm expecting.</p>
|
||||
<p>The beta is going to start with just the character sheet. You can play D&D without minis and maps, without a pre-written adventure, you can play without a lot of things, but the character sheet is necessary. So I'm starting here and working my way outwards.</p>
|
||||
<p>I will eventually have public bug tracking and feature requests going, but for now I'm going to track comments, feedback and suggestions on <a href="http://reddit.com/r/dicecloud">this subreddit</a>. If you've never used reddit before, all you need is a username and password to sign up. So it should be pretty accessible.</p>
|
||||
<h2>Character Sheet Philosophy</h2>
|
||||
<p>Setting up your character on Dicecloud is going to take you a little longer than just filling it in on a paper character sheet would have. The goal of using an online sheet is to make actually playing the game more streamlined, and ultimately more fun. So putting a little extra effort into setting up your character now will pay off over and over again once you're playing.</p>
|
||||
<p>The idea is to track where each number comes from, and allow you to easily make changes on the fly.</p>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<template name="home">
|
||||
<core-toolbar class="blue-grey white-text">
|
||||
<core-toolbar class="app-grey white-text">
|
||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||
<div flex>
|
||||
DiceCloud
|
||||
Home
|
||||
</div>
|
||||
</core-toolbar>
|
||||
<div class="scroll-y" style="padding: 16px" fit>
|
||||
{{> guide}}
|
||||
</div>
|
||||
{{> intro}}
|
||||
</template>
|
||||
@@ -1,25 +1,15 @@
|
||||
Template.home.helpers({
|
||||
characterDetails: function(){
|
||||
var char = Characters.findOne(
|
||||
this._id,
|
||||
{fields: {name: 1, gender: 1, alignment: 1, race:1}}
|
||||
);
|
||||
char.title = char.name;
|
||||
char.field = "base";
|
||||
char.color = "d";
|
||||
char.class = "characterCard";
|
||||
return char;
|
||||
}
|
||||
selectedTab: function(){
|
||||
return Session.get("homePage.selectedTab");
|
||||
},
|
||||
});
|
||||
|
||||
Template.home.events({
|
||||
"tap .characterCard": function(event, instance){
|
||||
Router.go("characterSheet", {_id: this._id});
|
||||
"core-animated-pages-transition-end .tabPages": function(event) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
"tap #addCharacter": function(event, template) {
|
||||
Characters.insert({owner: Meteor.userId()});
|
||||
},
|
||||
"tap #deleteChar": function(event, template){
|
||||
Characters.remove(this._id);
|
||||
"tap .homeTabs paper-tab": function(event, instance){
|
||||
Session.set("homePage.selectedTab",
|
||||
event.currentTarget.getAttribute("name"));
|
||||
},
|
||||
});
|
||||
|
||||
98
rpg-docs/client/views/home/intro/intro.html
Normal file
98
rpg-docs/client/views/home/intro/intro.html
Normal file
@@ -0,0 +1,98 @@
|
||||
<template name="intro">
|
||||
<div class="intro">
|
||||
<div class="section white-text" style="background: #282828">
|
||||
<div class="display2">
|
||||
Dice Cloud
|
||||
</div>
|
||||
<img style="width:130px; height:130px; background-color: #282828;"
|
||||
src="/crown-dice-logo-cropped-transparent.png">
|
||||
<div class="display1">
|
||||
Unofficial Online Realtime D&D 5e App
|
||||
</div>
|
||||
<h2>
|
||||
Spend less time shuffling paper and more time playing the game
|
||||
</h2>
|
||||
{{#unless currentUser}}
|
||||
<div layout horizontal around-justified wrap>
|
||||
<paper-button class="red white-text signInButton"
|
||||
style="margin: 16px;"
|
||||
raised>
|
||||
Sign In
|
||||
</paper-button>
|
||||
<paper-button class="red white-text signUpButton"
|
||||
style="margin: 16px;"
|
||||
raised>
|
||||
Sign Up
|
||||
</paper-button>
|
||||
</div>
|
||||
{{else}}
|
||||
<div style="padding-bottom: 0;"></div>
|
||||
{{/unless}}
|
||||
</div>
|
||||
<div class="section" style="background-color: #e9e9e9;">
|
||||
<div>
|
||||
<div class="display1">Character Sheet Open Beta</div>
|
||||
<h2 style="margin-bottom: 16px;">
|
||||
Check out the example characters
|
||||
</h2>
|
||||
<div layout horizontal around-justified wrap>
|
||||
<paper-shadow class="card characterCard ssArcher clickable"
|
||||
z="2">
|
||||
<div class="top subhead green white-text">
|
||||
<div class="subhead" flex>
|
||||
Starter Set Archer
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom text">Lawful Good Human</div>
|
||||
</paper-shadow>
|
||||
<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>
|
||||
<div class="section white-text" style="background: #282828">
|
||||
<div class="columns" layout horizontal around-justified wrap>
|
||||
<div>
|
||||
<h1>Check out the guide</h1>
|
||||
<p>
|
||||
Learn how your class gives you features, those features have effects,
|
||||
and those effects determine your stats.
|
||||
<paper-button class="guideButton">View Guide</paper-button>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
Discuss
|
||||
</h1>
|
||||
<p>
|
||||
On the official subreddit
|
||||
<paper-button class="redditButton">
|
||||
<a href="http://www.reddit.com/r/dicecloud/">
|
||||
/r/dicecloud
|
||||
</a>
|
||||
</paper-button>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
Get involved
|
||||
</h1>
|
||||
<p>Shape upcoming features and track bugs on the Dice Cloud Trello board
|
||||
<paper-button class="trelloButton">
|
||||
<a href="https://trello.com/b/94M0SCnq/dicecloud-roadmap">
|
||||
Trello Roadmap
|
||||
</a>
|
||||
</paper-button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
17
rpg-docs/client/views/home/intro/intro.js
Normal file
17
rpg-docs/client/views/home/intro/intro.js
Normal file
@@ -0,0 +1,17 @@
|
||||
Template.intro.events({
|
||||
"tap .signInButton": function() {
|
||||
Router.go("/sign-in");
|
||||
},
|
||||
"tap .signUpButton": function() {
|
||||
Router.go("/sign-up");
|
||||
},
|
||||
"tap .ssArcher": function() {
|
||||
Router.go("/character/yBWwt5XQTTHZiRQxq");
|
||||
},
|
||||
"tap .ssWizard": function() {
|
||||
Router.go("/character/KxHKskm22fS2Xogah");
|
||||
},
|
||||
"tap .guideButton": function() {
|
||||
Router.go("/guide");
|
||||
},
|
||||
});
|
||||
33
rpg-docs/client/views/home/intro/intro.scss
Normal file
33
rpg-docs/client/views/home/intro/intro.scss
Normal file
@@ -0,0 +1,33 @@
|
||||
.intro {
|
||||
.section {
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding-top: 24px;
|
||||
padding-bottom: 24px;
|
||||
& > div, & > h2 {
|
||||
padding: 32px;
|
||||
.display1 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
.columns > div{
|
||||
max-width: 300px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
paper-button {
|
||||
color: #FF5252;
|
||||
}
|
||||
}
|
||||
}
|
||||
paper-button {
|
||||
min-width: 200px;
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user