Implemented Features and Items granting effects, actions, attacks and spells
This commit is contained in:
21
README.md
21
README.md
@@ -1,13 +1,11 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
Strip the core interaction out of swipe-pages to create an element that just listens to swipe events
|
* Get Polymer installed using bower.
|
||||||
|
* Install Vulcanize package listed below
|
||||||
wishlist:
|
* Copy the differential polymer demo to get polymer implemented nicely
|
||||||
|
* Update Meteor
|
||||||
* swipes are emitted as an event if possible
|
* Install and use LESS
|
||||||
* swiping should translate the element
|
|
||||||
* it should bounce back to its resting position when released
|
|
||||||
|
|
||||||
Packages used
|
Packages used
|
||||||
=============
|
=============
|
||||||
@@ -48,8 +46,13 @@ Packages used
|
|||||||
* aldeed:autoform
|
* aldeed:autoform
|
||||||
* Automatically generates bootstrap forms for collection2 Schemas.
|
* Automatically generates bootstrap forms for collection2 Schemas.
|
||||||
* [github](https://github.com/aldeed/meteor-autoform)
|
* [github](https://github.com/aldeed/meteor-autoform)
|
||||||
|
* differential:vulcanize
|
||||||
|
* Bakes all the polymer imports into one file
|
||||||
|
* [github](https://github.com/Differential/meteor-vulcanize)
|
||||||
|
|
||||||
************
|
************
|
||||||
|
|
||||||
To Speed up builds when you know you wont need online package checking use
|
Resources
|
||||||
METEOR_OFFLINE_CATALOG=1
|
=========
|
||||||
|
|
||||||
|
[differential's polymer demo](https://github.com/Differential/polymer-demo)
|
||||||
|
|||||||
1
rpg-docs/.bowerrc
Normal file
1
rpg-docs/.bowerrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"directory":"public/components/"}
|
||||||
3
rpg-docs/.gitignore
vendored
Normal file
3
rpg-docs/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.meteor/local
|
||||||
|
.meteor/meteorite
|
||||||
|
public/components
|
||||||
@@ -1 +1 @@
|
|||||||
METEOR@1.0.1
|
METEOR@1.0.2.1
|
||||||
|
|||||||
@@ -1,77 +1,74 @@
|
|||||||
accounts-base@1.1.2
|
accounts-base@1.1.3
|
||||||
accounts-password@1.0.4
|
accounts-password@1.0.5
|
||||||
accounts-ui-unstyled@1.1.4
|
accounts-ui@1.1.4
|
||||||
accounts-ui@1.1.3
|
accounts-ui-unstyled@1.1.5
|
||||||
aldeed:autoform@4.1.0
|
aldeed:autoform@4.2.2
|
||||||
aldeed:collection2@2.2.0
|
aldeed:collection2@2.3.0
|
||||||
aldeed:simple-schema@1.1.0
|
aldeed:simple-schema@1.1.0
|
||||||
application-configuration@1.0.3
|
application-configuration@1.0.4
|
||||||
autoupdate@1.1.3
|
autoupdate@1.1.4
|
||||||
base64@1.0.1
|
base64@1.0.2
|
||||||
binary-heap@1.0.1
|
binary-heap@1.0.2
|
||||||
blaze-tools@1.0.1
|
blaze@2.0.4
|
||||||
blaze@2.0.3
|
blaze-tools@1.0.2
|
||||||
boilerplate-generator@1.0.1
|
boilerplate-generator@1.0.2
|
||||||
callback-hook@1.0.1
|
callback-hook@1.0.2
|
||||||
check@1.0.2
|
check@1.0.3
|
||||||
ctl-helper@1.0.4
|
|
||||||
ctl@1.0.2
|
|
||||||
cw4gn3r:jquery-event-drag@2.2.0
|
cw4gn3r:jquery-event-drag@2.2.0
|
||||||
dburles:collection-helpers@1.0.1
|
dburles:collection-helpers@1.0.2
|
||||||
ddp@1.0.12
|
ddp@1.0.13
|
||||||
deps@1.0.5
|
deps@1.0.6
|
||||||
ejson@1.0.4
|
ejson@1.0.5
|
||||||
email@1.0.4
|
email@1.0.5
|
||||||
fastclick@1.0.1
|
fastclick@1.0.2
|
||||||
follower-livedata@1.0.2
|
follower-livedata@1.0.3
|
||||||
geojson-utils@1.0.1
|
geojson-utils@1.0.2
|
||||||
html-tools@1.0.2
|
html-tools@1.0.3
|
||||||
htmljs@1.0.2
|
htmljs@1.0.3
|
||||||
http@1.0.8
|
http@1.0.9
|
||||||
id-map@1.0.1
|
id-map@1.0.2
|
||||||
insecure@1.0.1
|
insecure@1.0.2
|
||||||
iron:controller@1.0.3
|
iron:controller@1.0.6
|
||||||
iron:core@1.0.3
|
iron:core@1.0.6
|
||||||
iron:dynamic-template@1.0.3
|
iron:dynamic-template@1.0.6
|
||||||
iron:layout@1.0.3
|
iron:layout@1.0.6
|
||||||
iron:location@1.0.3
|
iron:location@1.0.6
|
||||||
iron:middleware-stack@1.0.3
|
iron:middleware-stack@1.0.6
|
||||||
iron:router@1.0.3
|
iron:router@1.0.6
|
||||||
iron:url@1.0.3
|
iron:url@1.0.6
|
||||||
jquery@1.0.1
|
jquery@1.0.2
|
||||||
json@1.0.1
|
json@1.0.2
|
||||||
launch-screen@1.0.0
|
launch-screen@1.0.1
|
||||||
less@1.0.11
|
less@1.0.12
|
||||||
livedata@1.0.11
|
livedata@1.0.12
|
||||||
localstorage@1.0.1
|
localstorage@1.0.2
|
||||||
logging@1.0.5
|
logging@1.0.6
|
||||||
meteor-platform@1.2.0
|
meteor@1.1.4
|
||||||
meteor@1.1.3
|
meteor-platform@1.2.1
|
||||||
minifiers@1.1.2
|
minifiers@1.1.3
|
||||||
minimongo@1.0.5
|
minimongo@1.0.6
|
||||||
mobile-status-bar@1.0.1
|
mobile-status-bar@1.0.2
|
||||||
mongo-livedata@1.0.6
|
momentjs:moment@2.8.4
|
||||||
mongo@1.0.9
|
mongo@1.0.11
|
||||||
mrt:moment@2.6.0
|
|
||||||
npm-bcrypt@0.7.7
|
npm-bcrypt@0.7.7
|
||||||
observe-sequence@1.0.3
|
observe-sequence@1.0.4
|
||||||
ordered-dict@1.0.1
|
ordered-dict@1.0.2
|
||||||
random@1.0.1
|
random@1.0.2
|
||||||
reactive-dict@1.0.4
|
reactive-dict@1.0.5
|
||||||
reactive-var@1.0.3
|
reactive-var@1.0.4
|
||||||
reload@1.1.1
|
reload@1.1.2
|
||||||
retry@1.0.1
|
retry@1.0.2
|
||||||
routepolicy@1.0.2
|
routepolicy@1.0.3
|
||||||
service-configuration@1.0.2
|
service-configuration@1.0.3
|
||||||
session@1.0.4
|
session@1.0.5
|
||||||
sha@1.0.1
|
sha@1.0.2
|
||||||
spacebars-compiler@1.0.3
|
spacebars@1.0.4
|
||||||
spacebars@1.0.3
|
spacebars-compiler@1.0.4
|
||||||
srp@1.0.1
|
srp@1.0.2
|
||||||
templating@1.0.9
|
templating@1.0.10
|
||||||
tracker@1.0.3
|
tracker@1.0.4
|
||||||
ui@1.0.4
|
ui@1.0.5
|
||||||
underscore@1.0.1
|
underscore@1.0.2
|
||||||
url@1.0.2
|
url@1.0.3
|
||||||
webapp-hashing@1.0.1
|
webapp@1.1.5
|
||||||
webapp@1.1.4
|
webapp-hashing@1.0.2
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Schemas.Character = new SimpleSchema({
|
|||||||
"proficiencyBonus.effects": {
|
"proficiencyBonus.effects": {
|
||||||
type: [Schemas.Effect],
|
type: [Schemas.Effect],
|
||||||
defaultValue: [
|
defaultValue: [
|
||||||
{name: "Proficiency bonus by level", calculation: "floor(level / 4.1) + 2", operation: "add", type: "inate"}
|
{name: "Proficiency bonus by level", calculation: "floor(level / 4 + 1.75)", operation: "add", type: "inate"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
speed: {type: Schemas.Attribute},
|
speed: {type: Schemas.Attribute},
|
||||||
@@ -68,6 +68,8 @@ Schemas.Character = new SimpleSchema({
|
|||||||
superiorityDice: {type: Schemas.Attribute},
|
superiorityDice: {type: Schemas.Attribute},
|
||||||
expertiseDice: {type: Schemas.Attribute},
|
expertiseDice: {type: Schemas.Attribute},
|
||||||
|
|
||||||
|
//specific features
|
||||||
|
rageDamage: {type: Schemas.Attribute},
|
||||||
|
|
||||||
//hit dice
|
//hit dice
|
||||||
d6HitDice: {type: Schemas.Attribute},
|
d6HitDice: {type: Schemas.Attribute},
|
||||||
@@ -174,52 +176,24 @@ Schemas.Character = new SimpleSchema({
|
|||||||
|
|
||||||
strengthAttack: {type: Schemas.Skill},
|
strengthAttack: {type: Schemas.Skill},
|
||||||
"strengthAttack.ability": {type: String,defaultValue: "strength"},
|
"strengthAttack.ability": {type: String,defaultValue: "strength"},
|
||||||
"strengthAttack.effects": {
|
|
||||||
type: [Schemas.Effect],
|
|
||||||
defaultValue: [{name: "Attack Proficiency", value: 1, operation: "proficiency", type: "inate"}]
|
|
||||||
},
|
|
||||||
|
|
||||||
dexterityAttack: {type: Schemas.Skill},
|
dexterityAttack: {type: Schemas.Skill},
|
||||||
"dexterityAttack.ability": { type: String, defaultValue: "dexterity" },
|
"dexterityAttack.ability": { type: String, defaultValue: "dexterity" },
|
||||||
"dexterityAttack.proficiency": {
|
|
||||||
type: [Schemas.Effect],
|
|
||||||
defaultValue: [{name: "Attack Proficiency", value: 1, operation: "proficiency", type: "inate"}]
|
|
||||||
},
|
|
||||||
|
|
||||||
constitutionAttack: {type: Schemas.Skill},
|
constitutionAttack: {type: Schemas.Skill},
|
||||||
"constitutionAttack.ability":{ type: String, defaultValue: "constitution" },
|
"constitutionAttack.ability":{ type: String, defaultValue: "constitution" },
|
||||||
"constitutionAttack.proficiency": {
|
|
||||||
type: [Schemas.Effect],
|
|
||||||
defaultValue: [{name: "Attack Proficiency", value: 1, operation: "proficiency", type: "inate"}]
|
|
||||||
},
|
|
||||||
|
|
||||||
intelligenceAttack: {type: Schemas.Skill},
|
intelligenceAttack: {type: Schemas.Skill},
|
||||||
"intelligenceAttack.ability":{ type: String, defaultValue: "intelligence" },
|
"intelligenceAttack.ability":{ type: String, defaultValue: "intelligence" },
|
||||||
"intelligenceAttack.proficiency": {
|
|
||||||
type: [Schemas.Effect],
|
|
||||||
defaultValue: [{name: "Attack Proficiency", value: 1, operation: "proficiency", type: "inate"}]
|
|
||||||
},
|
|
||||||
|
|
||||||
wisdomAttack: {type: Schemas.Skill},
|
wisdomAttack: {type: Schemas.Skill},
|
||||||
"wisdomAttack.ability": { type: String, defaultValue: "wisdom" },
|
"wisdomAttack.ability": { type: String, defaultValue: "wisdom" },
|
||||||
"wisdomAttack.proficiency": {
|
|
||||||
type: [Schemas.Effect],
|
|
||||||
defaultValue: [{name: "Attack Proficiency", value: 1, operation: "proficiency", type: "inate"}]
|
|
||||||
},
|
|
||||||
|
|
||||||
charismaAttack: {type: Schemas.Skill},
|
charismaAttack: {type: Schemas.Skill},
|
||||||
"charismaAttack.ability": { type: String, defaultValue: "charisma" },
|
"charismaAttack.ability": { type: String, defaultValue: "charisma" },
|
||||||
"charismaAttack.proficiency": {
|
|
||||||
type: [Schemas.Effect],
|
|
||||||
defaultValue: [{name: "Attack Proficiency", value: 1, operation: "proficiency", type: "inate"}]
|
|
||||||
},
|
|
||||||
|
|
||||||
rangedAttack: {type: Schemas.Skill},
|
rangedAttack: {type: Schemas.Skill},
|
||||||
"rangedAttack.ability": { type: String, defaultValue: "dexterity" },
|
"rangedAttack.ability": { type: String, defaultValue: "dexterity" },
|
||||||
"rangedAttack.proficiency": {
|
|
||||||
type: [Schemas.Effect],
|
|
||||||
defaultValue: [{name: "Attack Proficiency", value: 1, operation: "proficiency", type: "inate"}]
|
|
||||||
},
|
|
||||||
|
|
||||||
dexterityArmor: {type: Schemas.Skill},
|
dexterityArmor: {type: Schemas.Skill},
|
||||||
"dexterityArmor.ability": { type: String, defaultValue: "dexterity" },
|
"dexterityArmor.ability": { type: String, defaultValue: "dexterity" },
|
||||||
@@ -239,19 +213,22 @@ Schemas.Character = new SimpleSchema({
|
|||||||
},
|
},
|
||||||
|
|
||||||
//mechanics
|
//mechanics
|
||||||
features: { type: [Schemas.Feature], defaultValue: []},
|
features: { type: [String], defaultValue: [], regEx: SimpleSchema.RegEx.Id,},
|
||||||
|
customFeatures: { type: [Schemas.Feature], defaultValue: []},
|
||||||
|
actions: { type: [Schemas.Action], defaultValue: []},
|
||||||
deathSave: { type: Schemas.DeathSave },
|
deathSave: { type: Schemas.DeathSave },
|
||||||
time: { type: Number, min: 0, decimal: true, defaultValue: 0},
|
time: { type: Number, min: 0, decimal: true, defaultValue: 0},
|
||||||
initiativeOrder:{ type: Number, min: 0, max: 1, decimal: true, defaultValue: 0},
|
initiativeOrder:{ type: Number, min: 0, max: 1, decimal: true, defaultValue: 0},
|
||||||
expirations: { type: [Schemas.Expiration], defaultValue: []},
|
buffs: { type: [Schemas.Buff], defaultValue: []}
|
||||||
spells: { type: [Schemas.Spell], defaultValue: []}
|
|
||||||
//TODO add permission stuff for owner, readers and writers
|
//TODO add permission stuff for owner, readers and writers
|
||||||
|
//TODO add per-character settings
|
||||||
});
|
});
|
||||||
|
|
||||||
Characters.attachSchema(Schemas.Character);
|
Characters.attachSchema(Schemas.Character);
|
||||||
|
|
||||||
//reactively remove expired effects
|
//reactively remove expired effects
|
||||||
//this can be optimised a lot once clients can do projections
|
//TODO broken with the move from expirations -> buffs
|
||||||
|
//TODO fix by finding every buff whose expiry is >= current time, pull those buffs
|
||||||
Characters.find({},{fields: {time: 1, expirations: 1, features: 1}}).observe({
|
Characters.find({},{fields: {time: 1, expirations: 1, features: 1}}).observe({
|
||||||
changed: function(character){
|
changed: function(character){
|
||||||
var currentTime = character.time;
|
var currentTime = character.time;
|
||||||
@@ -276,25 +253,38 @@ Characters.find({},{fields: {time: 1, expirations: 1, features: 1}}).observe({
|
|||||||
});
|
});
|
||||||
|
|
||||||
var attributeBase = function(charId, attribute){
|
var attributeBase = function(charId, attribute){
|
||||||
|
var effects = _.groupBy(attribute.effects, "operation");
|
||||||
var value = 0;
|
var value = 0;
|
||||||
_.each(attribute.effects, function(effect){
|
|
||||||
switch(effect.operation) {
|
//start with the highest base value
|
||||||
case "add":
|
_.each(effects.base, function(effect){
|
||||||
value += evaluateEffect(charId, effect);
|
var efv = evaluateEffect(charId, effect)
|
||||||
break;
|
if (effect.value > value){
|
||||||
case "mul":
|
value = effect.value;
|
||||||
value *= evaluateEffect(charId, effect);
|
|
||||||
break;
|
|
||||||
case "min":
|
|
||||||
var min = evaluateEffect(charId, effect);
|
|
||||||
value = value > min? value : min;
|
|
||||||
break;
|
|
||||||
case "max":
|
|
||||||
var max = evaluateEffect(charId, effect);
|
|
||||||
value = value < max? value : max;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//add all the add values
|
||||||
|
_.each(effects.add, function(effect){
|
||||||
|
value += evaluateEffect(charId, effect);
|
||||||
|
});
|
||||||
|
|
||||||
|
//multiply all the mul values
|
||||||
|
_.each(effects.mul, function(effect){
|
||||||
|
value *= evaluateEffect(charId, effect);
|
||||||
|
});
|
||||||
|
|
||||||
|
//ensure value is >= all mins
|
||||||
|
_.each(effects.min, function(effect){
|
||||||
|
var min = evaluateEffect(charId, effect);
|
||||||
|
value = value > min? value : min;
|
||||||
|
});
|
||||||
|
|
||||||
|
//ensure value is <= all maxes
|
||||||
|
_.each(effects.max, function(effect){
|
||||||
|
var max = evaluateEffect(charId, effect);
|
||||||
|
value = value < max? value : max;
|
||||||
|
});
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +299,7 @@ Characters.helpers({
|
|||||||
fieldSelector[fieldName] = 1;
|
fieldSelector[fieldName] = 1;
|
||||||
var char = Characters.findOne(this._id, {fields: fieldSelector});
|
var char = Characters.findOne(this._id, {fields: fieldSelector});
|
||||||
var field = char[fieldName];
|
var field = char[fieldName];
|
||||||
if(!field){
|
if(field === undefined){
|
||||||
throw new Meteor.Error("getField failed",
|
throw new Meteor.Error("getField failed",
|
||||||
"getField could not find field " + fieldName + " in character "+ char._id);
|
"getField could not find field " + fieldName + " in character "+ char._id);
|
||||||
}
|
}
|
||||||
@@ -333,35 +323,15 @@ Characters.helpers({
|
|||||||
return this.getField(fieldName);
|
return this.getField(fieldName);
|
||||||
},
|
},
|
||||||
|
|
||||||
attributeValue: (function(){
|
attributeValue: function(attributeName){
|
||||||
//store a private array of attributes we've visited without returning
|
var charId = this._id;
|
||||||
//if we try to visit the same attribute twice before resolving its value
|
var attribute = this.getField(attributeName);
|
||||||
//we are in a dependency loop and need to GTFO
|
//base value
|
||||||
var visitedAttributes = [];
|
var value = this.attributeBase(attributeName);
|
||||||
return function(attributeName){
|
//plus adjustment
|
||||||
check(attributeName, String);
|
value += attribute.adjustment;
|
||||||
//we're still evaluating this attribute, must be in a loop
|
return value;
|
||||||
if(_.contains(visitedAttributes, attributeName)) {
|
},
|
||||||
console.log("dependency loop detected");
|
|
||||||
return NaN;
|
|
||||||
}
|
|
||||||
//push this attribute to the list of visited attributes
|
|
||||||
//we can't visit it again unless it returns first
|
|
||||||
visitedAttributes.push(attributeName);
|
|
||||||
|
|
||||||
try{
|
|
||||||
var charId = this._id;
|
|
||||||
var attribute = this.getField(attributeName);
|
|
||||||
//base value
|
|
||||||
var value = attributeBase(charId, attribute);
|
|
||||||
value += attribute.adjustment;
|
|
||||||
}finally{
|
|
||||||
//this attribute returns or fails, pull it from the array, we may visit it again safely
|
|
||||||
visitedAttributes = _.without(visitedAttributes, attributeName);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
})(),
|
|
||||||
|
|
||||||
attributeBase: (function(){
|
attributeBase: (function(){
|
||||||
//store a private array of attributes we've visited without returning
|
//store a private array of attributes we've visited without returning
|
||||||
|
|||||||
42
rpg-docs/Model/Character/Features.js
Normal file
42
rpg-docs/Model/Character/Features.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
//Features are features that can be selected but not edited
|
||||||
|
//they are the things that come in the player's handbook and
|
||||||
|
//facilitate the quick building of characters
|
||||||
|
//They are the primary means of collecting cease and desist letters :(
|
||||||
|
//
|
||||||
|
//Should only be edited by admins
|
||||||
|
//
|
||||||
|
//TODO add a Meteor Method that lets users add a feature to their character
|
||||||
|
//and pushes the effects and actions accordingly
|
||||||
|
//
|
||||||
|
//TODO add a Method that updates every character with a given feature if that feature should change
|
||||||
|
|
||||||
|
Features = new Meteor.Collection("features");
|
||||||
|
|
||||||
|
Schemas.Feature = new SimpleSchema({
|
||||||
|
_id: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
|
autoValue: function(){
|
||||||
|
if(!this.isSet) return Random.id();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {type: String},
|
||||||
|
description:{type: String, optional: true},
|
||||||
|
source: {type: String, optional: true},
|
||||||
|
effects: {type: [Schemas.Effect], defaultValue: []},
|
||||||
|
actions: {type: [Schemas.Action], defaultValue: []},
|
||||||
|
attacks: {type: [Schemas.Attack], defaultValue: []},
|
||||||
|
spells: {type: [Schemas.Spell] , defaultValue: []},
|
||||||
|
});
|
||||||
|
|
||||||
|
Features.attachSchema(Schemas.Feature);
|
||||||
|
|
||||||
|
//observe standard features for changes and update characters using them
|
||||||
|
Features.find().observe({
|
||||||
|
changed: function(newFeature, oldFeature){
|
||||||
|
//TODO
|
||||||
|
},
|
||||||
|
removed: function(oldFeature){
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
});
|
||||||
29
rpg-docs/Model/Character/SubSchemas/Action.js
Normal file
29
rpg-docs/Model/Character/SubSchemas/Action.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Actions are given to a character by items and features
|
||||||
|
*/
|
||||||
|
Schemas.Action = new SimpleSchema({
|
||||||
|
_id: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
|
autoValue: function(){
|
||||||
|
if(!this.isSet) return Random.id();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
allowedValues: ["action, bonus, reaction, free"],
|
||||||
|
defaultValue: "action"
|
||||||
|
},
|
||||||
|
selfBuffs: {
|
||||||
|
type: [Schemas.Buff], defaultValue: []
|
||||||
|
},
|
||||||
|
selfAdjustments: {
|
||||||
|
type: [Schemas.Adjustment], defaultValue: []
|
||||||
|
}
|
||||||
|
});
|
||||||
25
rpg-docs/Model/Character/SubSchemas/Adjustment.js
Normal file
25
rpg-docs/Model/Character/SubSchemas/Adjustment.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Adjustments make instantaneous changes to the value of some attribute
|
||||||
|
* 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,
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
//the value added to the stat
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
decimal: true,
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
calculation: {
|
||||||
|
type: String,
|
||||||
|
optional: true
|
||||||
|
}
|
||||||
|
});
|
||||||
31
rpg-docs/Model/Character/SubSchemas/Attack.js
Normal file
31
rpg-docs/Model/Character/SubSchemas/Attack.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Attacks are given to a character by items and features
|
||||||
|
*/
|
||||||
|
Schemas.Attack = new SimpleSchema({
|
||||||
|
_id: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
|
autoValue: function(){
|
||||||
|
if(!this.isSet) return Random.id();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
range: {
|
||||||
|
type: String,
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
attackBonus: {
|
||||||
|
type: String,
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
damageType: {
|
||||||
|
type: String,
|
||||||
|
allowedValues: ["acid", "bludgeoning", "cold", "fire", "force", "lightning", "necrotic",
|
||||||
|
"piercing", "poison", "psychic", "radiant", "slashing", "thunder"]
|
||||||
|
}
|
||||||
|
});
|
||||||
18
rpg-docs/Model/Character/SubSchemas/Buff.js
Normal file
18
rpg-docs/Model/Character/SubSchemas/Buff.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//buffs are temporary once applied and store things which expire and their expiry time
|
||||||
|
Schemas.Buff = new SimpleSchema({
|
||||||
|
//buff id
|
||||||
|
_id: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
|
autoValue: function(){
|
||||||
|
if(!this.isSet) return Random.id();
|
||||||
|
}},
|
||||||
|
|
||||||
|
//things that expire
|
||||||
|
effects: { type: [Schemas.Effect], defaultValue: [] },
|
||||||
|
actions: { type: [Schemas.Action], defaultValue: [] },
|
||||||
|
|
||||||
|
//expiry time
|
||||||
|
expiry: { type: Number, optional: true},
|
||||||
|
duration: { type: Number }
|
||||||
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Effects are reason-value pairs attached to skills and abilities
|
* Effects are reason-value attached to skills and abilities
|
||||||
* that modify their final value or presentation in some way
|
* that modify their final value or presentation in some way
|
||||||
*/
|
*/
|
||||||
Schemas.Effect = new SimpleSchema({
|
Schemas.Effect = new SimpleSchema({
|
||||||
@@ -16,7 +16,7 @@ Schemas.Effect = new SimpleSchema({
|
|||||||
operation: {
|
operation: {
|
||||||
type: String,
|
type: String,
|
||||||
defaultValue: "add",
|
defaultValue: "add",
|
||||||
allowedValues: ["proficiency","add","mul","min","max","advantage","disadvantage","passiveAdd","fail","conditional","passiveAdd"]
|
allowedValues: ["base", "proficiency","add","mul","min","max","advantage","disadvantage","passiveAdd","fail","conditional","passiveAdd"]
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@@ -32,5 +32,10 @@ Schemas.Effect = new SimpleSchema({
|
|||||||
type: String,
|
type: String,
|
||||||
defaultValue: "editable",
|
defaultValue: "editable",
|
||||||
allowedValues: ["editable", "feat", "buff", "equipment", "inate"]
|
allowedValues: ["editable", "feat", "buff", "equipment", "inate"]
|
||||||
|
},
|
||||||
|
//which stat the effect is applied to
|
||||||
|
stat: {
|
||||||
|
type: String,
|
||||||
|
optional: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/*
|
|
||||||
* A buff becomes an effect when applied on a creature.
|
|
||||||
* It is the effect plus the stat to which it should be applied
|
|
||||||
*/
|
|
||||||
Schemas.Buff = new SimpleSchema({
|
|
||||||
stat: {
|
|
||||||
type: String
|
|
||||||
},
|
|
||||||
effect: {
|
|
||||||
type: Schemas.Effect
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
//schema to store all effects which expire and their expiry dates
|
|
||||||
Schemas.Expiration = new SimpleSchema({
|
|
||||||
_id: {
|
|
||||||
type: String,
|
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
|
||||||
autoValue: function(){
|
|
||||||
if(!this.isSet) return Random.id();
|
|
||||||
}},
|
|
||||||
stat: { type: String },
|
|
||||||
effectIds: { type: [String], regEx: SimpleSchema.RegEx.Id },
|
|
||||||
featureIds:{ type: [String], regEx: SimpleSchema.RegEx.Id },
|
|
||||||
expiry: { type: Number }
|
|
||||||
});
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
Schemas.Feature = new SimpleSchema({
|
|
||||||
_id: {
|
|
||||||
type: String,
|
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
|
||||||
autoValue: function(){
|
|
||||||
if(!this.isSet) return Random.id();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
name: {type: String},
|
|
||||||
description:{type: String},
|
|
||||||
source: {type: String},
|
|
||||||
buffs: {type: [Schemas.Buff], defaultValue: []},
|
|
||||||
enabled: {type: Boolean, defaultValue: false},
|
|
||||||
duration: {type: Number, optional: true},
|
|
||||||
uses: {type: Number, min: 0, optional: true},
|
|
||||||
maxUses: {type: Number, min: 0, optional: true},
|
|
||||||
reset: {
|
|
||||||
type: String,
|
|
||||||
optional: true,
|
|
||||||
allowedValues: ["longRest", "shortRest"]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -13,8 +13,10 @@ Schemas.Spell = new SimpleSchema({
|
|||||||
duration: {type: Number},
|
duration: {type: Number},
|
||||||
"components.verbal": {type: Boolean},
|
"components.verbal": {type: Boolean},
|
||||||
"components.somatic": {type: Boolean},
|
"components.somatic": {type: Boolean},
|
||||||
"components.material": {type: String},
|
"components.material": {type: String, optional: true},
|
||||||
"components.concentration": {type: Boolean},
|
"components.concentration": {type: Boolean},
|
||||||
buffs: {type: [Schemas.Buff], optional: true},
|
ritual: {type: Boolean},
|
||||||
|
selfBuffs: {type: [Schemas.Buff], defaultValue: []},
|
||||||
level: {type: Number},
|
level: {type: Number},
|
||||||
|
class: {type: String}
|
||||||
});
|
});
|
||||||
@@ -4,18 +4,42 @@ Schemas.Item = new SimpleSchema({
|
|||||||
name: {type: String, defaultValue: "New Item"},
|
name: {type: String, defaultValue: "New Item"},
|
||||||
plural: {type: String, optional: true},
|
plural: {type: String, optional: true},
|
||||||
description:{type: String, defaultValue: ""},
|
description:{type: String, defaultValue: ""},
|
||||||
container: {type: String, regEx: SimpleSchema.RegEx.Id},
|
container: {type: String}, //id of container it normally is stowed in
|
||||||
|
character: {type: String, regEx: SimpleSchema.RegEx.Id}, //id of owner
|
||||||
quantity: {type: Number, min: 0, defaultValue: 1},
|
quantity: {type: Number, min: 0, defaultValue: 1},
|
||||||
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||||
tradeGood: {type: Boolean, defaultValue: false},
|
tradeGood: {type: Boolean, defaultValue: false},
|
||||||
stackable: {type: Boolean, defaultValue: false},
|
stackable: {type: Boolean, defaultValue: false},
|
||||||
buffs: {type: [Schemas.Buff], defaultValue: []},
|
feature: {type: Schemas.Feature},
|
||||||
equipmentSlot: {type: String, defaultValue: "", allowedValues: ["head", "body", "arms", "hands", "held", "feet"]},
|
equipmentSlot: {
|
||||||
|
type: String,
|
||||||
|
defaultValue: "none",
|
||||||
|
allowedValues: ["none", "head", "armor", "arms", "hands", "held", "feet"]
|
||||||
|
},
|
||||||
|
equipped: {type: Boolean, defaultValue: false}
|
||||||
});
|
});
|
||||||
|
|
||||||
Items.attachSchema(Schemas.Item);
|
Items.attachSchema(Schemas.Item);
|
||||||
|
|
||||||
|
//update the features of the items as needed
|
||||||
|
Items.find({}, {fields: {feature: 1, character: 1, equipped: 1}}).observe({
|
||||||
|
added: function(newItem){
|
||||||
|
if(newItem.feature && newItem.character)
|
||||||
|
addFeatureEffects(newItem.character, newItem.feature);
|
||||||
|
},
|
||||||
|
changed: function(newItem, oldItem){
|
||||||
|
if(oldItem.feature && oldItem.character)
|
||||||
|
removeFeatureEffects(oldItem.character, oldItem.feature);
|
||||||
|
if(newItem.feature && newItem.character)
|
||||||
|
addFeatureEffects(newItem.character, newItem.feature);
|
||||||
|
},
|
||||||
|
removed: function(oldItem){
|
||||||
|
if(oldItem.feature && oldItem.character)
|
||||||
|
removeFeatureEffects(oldItem.character, oldItem.feature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Items.helpers({
|
Items.helpers({
|
||||||
totalValue: function(){
|
totalValue: function(){
|
||||||
return this.value * this.quantity;
|
return this.value * this.quantity;
|
||||||
|
|||||||
25
rpg-docs/bower.json
Normal file
25
rpg-docs/bower.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "RPG Docs",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"homepage": "",
|
||||||
|
"authors": ["Stefan Zermatten"],
|
||||||
|
"license": "none",
|
||||||
|
"private": true,
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"polymer": "Polymer/polymer#~0.5.2",
|
||||||
|
"core-elements": "Polymer/core-elements#~0.5.2",
|
||||||
|
"paper-elements": "Polymer/paper-elements#~0.5.2"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"core-component-page": "^0.5.0",
|
||||||
|
"polymer": "^0.5.0",
|
||||||
|
"webcomponentsjs": "^0.5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,7 +58,6 @@ paper-button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
width: 148px;
|
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -67,7 +66,7 @@ paper-button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card.double {
|
.card.double {
|
||||||
width: 304px;
|
width: 332px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card paper-button {
|
.card paper-button {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ h1, .headline {
|
|||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.white-text h1, .white-text .headline{
|
.white-text h1, .white-text .headline, .white-text.headline{
|
||||||
color: rgba(255,255,255,0.87);
|
color: rgba(255,255,255,0.87);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
<template name="features">
|
|
||||||
{{#each features}}
|
|
||||||
<li><strong>{{name}}</strong><input class="enabled" type="checkbox" checked={{enabled}}><br>
|
|
||||||
{{# each effects}}
|
|
||||||
{{stat}}: {{value}}
|
|
||||||
{{/each}}</li>
|
|
||||||
{{/each}}
|
|
||||||
</template>
|
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#stats .card {
|
#stats .card {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
max-width: 480px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#stats .abilityFlex{
|
#stats .abilityFlex{
|
||||||
@@ -25,6 +26,26 @@
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attribute.card, .skill.card {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-top {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 2px 2px 0 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card .subhead {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.editEffect > * {
|
.editEffect > * {
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
@@ -35,6 +56,14 @@
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#armorHeading {
|
||||||
|
background: url(/jpg/rusted-metal-armor.jpg) no-repeat;
|
||||||
|
-webkit-background-size: cover;
|
||||||
|
-moz-background-size: cover;
|
||||||
|
-o-background-size: cover;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
#detailContainer {
|
#detailContainer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -4,73 +4,6 @@
|
|||||||
<div class="abilityFlex">
|
<div class="abilityFlex">
|
||||||
{{> abilityCards}}
|
{{> abilityCards}}
|
||||||
</div>
|
</div>
|
||||||
<div class="statsFlex">
|
|
||||||
<paper-shadow {{isHero "armor"}} class="card attribute" hero-id="armor">
|
|
||||||
<h1>{{attributeValue "armor"}}</h1>
|
|
||||||
<p class="caption">Armor</p>
|
|
||||||
</paper-shadow>
|
|
||||||
<paper-shadow {{isHero "initiative"}} class="card skill" hero-id="initiative">
|
|
||||||
<h1>{{skillMod "initiative"}}</h1>
|
|
||||||
<p class="caption">Initiative</p>
|
|
||||||
</paper-shadow>
|
|
||||||
<paper-shadow {{isHero "proficiencyBonus"}} class="card attribute" hero-id="proficiencyBonus">
|
|
||||||
<h1>{{attributeValue "proficiencyBonus"}}</h1>
|
|
||||||
<p class="caption">Proficiency Bonus</p>
|
|
||||||
</paper-shadow>
|
|
||||||
<paper-shadow {{isHero "speed"}} class="card attribute" hero-id="speed">
|
|
||||||
<h1>{{attributeValue "speed"}}</h1>
|
|
||||||
<p class="caption">Speed</p>
|
|
||||||
</paper-shadow>
|
|
||||||
<paper-shadow {{isHero "passivePerception"}} class="card" hero-id="passivePerception">
|
|
||||||
<h1>{{passiveSkill "perception"}}</h1>
|
|
||||||
<p class="caption">Passive Perception</p>
|
|
||||||
</paper-shadow>
|
|
||||||
<paper-shadow class="card" id="hitDice">
|
|
||||||
<h1 class="attribute" hero-id="d6HitDice" {{isHero "d6HitDice"}}>
|
|
||||||
{{> hitDice hitDice="d6HitDice" d="6"}}
|
|
||||||
</h1>
|
|
||||||
<h1 class="attribute" hero-id="d8HitDice" {{isHero "d8HitDice"}}>
|
|
||||||
{{> hitDice hitDice="d8HitDice" d="8"}}
|
|
||||||
</h1>
|
|
||||||
<h1 class="attribute" hero-id="d10HitDice" {{isHero "d10HitDice"}}>
|
|
||||||
{{> hitDice hitDice="d10HitDice" d="10"}}
|
|
||||||
</h1>
|
|
||||||
<h1 class="attribute" hero-id="d12HitDice" {{isHero "d12HitDice"}}>
|
|
||||||
{{> hitDice hitDice="d12HitDice" d="12"}}
|
|
||||||
</h1>
|
|
||||||
<p class="caption">Hit Dice</p>
|
|
||||||
</paper-shadow>
|
|
||||||
{{# if canCast}}
|
|
||||||
<paper-shadow class="card" id="spellSlots">
|
|
||||||
<h1>{{> spellSlots}}</h1>
|
|
||||||
<p class="caption">Spell Slots</p>
|
|
||||||
</paper-shadow>
|
|
||||||
{{/if}}
|
|
||||||
{{# if attributeBase "rages"}}
|
|
||||||
<paper-shadow class="card" id="rages">
|
|
||||||
<h1>{{attributeValue "rages"}}</h1>
|
|
||||||
<p class="caption">rages</p>
|
|
||||||
</paper-shadow>
|
|
||||||
{{/if}}
|
|
||||||
{{# if attributeBase "sorceryPoints"}}
|
|
||||||
<paper-shadow class="card" id="sorceryPoints">
|
|
||||||
<h1>{{attributeValue "sorceryPoints"}}</h1>
|
|
||||||
<p class="caption">Sorcery Points</p>
|
|
||||||
</paper-shadow>
|
|
||||||
{{/if}}
|
|
||||||
{{# if attributeBase "expertiseDice"}}
|
|
||||||
<paper-shadow class="card" id="expertiseDice">
|
|
||||||
<h1>{{attributeValue "expertiseDice"}}</h1>
|
|
||||||
<p class="caption">Expertise Dice</p>
|
|
||||||
</paper-shadow>
|
|
||||||
{{/if}}
|
|
||||||
{{# if attributeBase "superiorityDice"}}
|
|
||||||
<paper-shadow class="card" id="superiorityDice">
|
|
||||||
<h1>{{attributeValue "superiorityDice"}}</h1>
|
|
||||||
<p class="caption">Superiority Dice</p>
|
|
||||||
</paper-shadow>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
<section id="detailContainer">
|
<section id="detailContainer">
|
||||||
<div cross-fade id="darkOverlay"></div>
|
<div cross-fade id="darkOverlay"></div>
|
||||||
@@ -80,12 +13,6 @@
|
|||||||
</core-animated-pages>
|
</core-animated-pages>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="hitDice">
|
|
||||||
{{# if ../attributeBase hitDice}}
|
|
||||||
{{../attributeValue hitDice}}d{{d}} + {{../abilityMod "constitution"}}
|
|
||||||
{{/if}}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template name="spellSlots">
|
<template name="spellSlots">
|
||||||
{{attributeValue "level1SpellSlots"}}
|
{{attributeValue "level1SpellSlots"}}
|
||||||
{{attributeValue "level2SpellSlots"}}
|
{{attributeValue "level2SpellSlots"}}
|
||||||
@@ -98,6 +25,17 @@
|
|||||||
{{attributeValue "level9SpellSlots"}}
|
{{attributeValue "level9SpellSlots"}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="statCard">
|
||||||
|
<paper-shadow {{isHero id}} class="card {{type}}" hero-id={{id}}>
|
||||||
|
<div id="{{id}}Heading" class="card-top headline {{class}}">
|
||||||
|
{{> UI.contentBlock}}
|
||||||
|
</div>
|
||||||
|
<div class="subhead">
|
||||||
|
{{title}}
|
||||||
|
</div>
|
||||||
|
</paper-shadow>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template name="attributeDialog">
|
<template name="attributeDialog">
|
||||||
<!--needs character, attributeName, attributeTitle-->
|
<!--needs character, attributeName, attributeTitle-->
|
||||||
{{#if attributeName}}
|
{{#if attributeName}}
|
||||||
|
|||||||
@@ -55,6 +55,15 @@ Template.stats.helpers({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Template.statCard.helpers({
|
||||||
|
isHero: function(string){
|
||||||
|
if(string === Session.get("selectedAttribute")||
|
||||||
|
string === Session.get("selectedSkill")){
|
||||||
|
return "hero";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Template.attributeDialog.helpers({
|
Template.attributeDialog.helpers({
|
||||||
attributeTitle: function(){
|
attributeTitle: function(){
|
||||||
return Session.get("selectedAttributeTitle");
|
return Session.get("selectedAttributeTitle");
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
background-color: #D50000;
|
background-color: #D50000;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
border-radius: 2px 0 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.abilityFlex .card {
|
.abilityFlex .card {
|
||||||
@@ -20,10 +21,11 @@
|
|||||||
|
|
||||||
.abilityCardRight {
|
.abilityCardRight {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.abilityCardRight hr{
|
.abilityCardRight hr{
|
||||||
margin: 8px -16px;
|
margin: 8px 0 8px -16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.abilityCardRight h1{
|
.abilityCardRight h1{
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
<div class="abilityCardRight">
|
<div class="abilityCardRight">
|
||||||
<h1>Dexterity</h1>
|
<h1>Dexterity</h1>
|
||||||
{{> skillRow name="Save" skill="dexteritySave"}}
|
{{> skillRow name="Save" skill="dexteritySave"}}
|
||||||
|
{{> skillRow name="Initiative" skill="initiative"}}
|
||||||
<hr>
|
<hr>
|
||||||
{{> skillRow name="Acrobatics" skill="acrobatics"}}
|
{{> skillRow name="Acrobatics" skill="acrobatics"}}
|
||||||
{{> skillRow name="Sleight of Hand" skill="sleightOfHand"}}
|
{{> skillRow name="Sleight of Hand" skill="sleightOfHand"}}
|
||||||
@@ -52,6 +53,18 @@
|
|||||||
<h1>Constitution</h1>
|
<h1>Constitution</h1>
|
||||||
{{> skillRow name="Save" skill="constitutionSave"}}
|
{{> skillRow name="Save" skill="constitutionSave"}}
|
||||||
<hr>
|
<hr>
|
||||||
|
<h1 class="attribute" hero-id="d6HitDice">
|
||||||
|
{{> hitDice hitDice="d6HitDice" d="6"}}
|
||||||
|
</h1>
|
||||||
|
<h1 class="attribute" hero-id="d8HitDice">
|
||||||
|
{{> hitDice hitDice="d8HitDice" d="8"}}
|
||||||
|
</h1>
|
||||||
|
<h1 class="attribute" hero-id="d10HitDice">
|
||||||
|
{{> hitDice hitDice="d10HitDice" d="10"}}
|
||||||
|
</h1>
|
||||||
|
<h1 class="attribute" hero-id="d12HitDice">
|
||||||
|
{{> hitDice hitDice="d12HitDice" d="12"}}
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</paper-shadow>
|
</paper-shadow>
|
||||||
</template>
|
</template>
|
||||||
@@ -90,7 +103,7 @@
|
|||||||
{{> skillRow name="Animal Handling" skill="animalHandling"}}
|
{{> skillRow name="Animal Handling" skill="animalHandling"}}
|
||||||
{{> skillRow name="Insight" skill="insight"}}
|
{{> skillRow name="Insight" skill="insight"}}
|
||||||
{{> skillRow name="Medicine" skill="medicine"}}
|
{{> skillRow name="Medicine" skill="medicine"}}
|
||||||
{{> skillRow name="Perception" skill="perception"}}
|
{{> skillRow name="Perception" skill="perception" showPassive="true"}}
|
||||||
{{> skillRow name="Survival" skill="survival"}}
|
{{> skillRow name="Survival" skill="survival"}}
|
||||||
</div>
|
</div>
|
||||||
</paper-shadow>
|
</paper-shadow>
|
||||||
@@ -114,3 +127,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</paper-shadow>
|
</paper-shadow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="hitDice">
|
||||||
|
{{# if ../attributeBase hitDice}}
|
||||||
|
{{../attributeValue hitDice}}d{{d}} {{../abilityMod "constitution"}}
|
||||||
|
{{/if}}
|
||||||
|
</template>
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
<paper-tab>Stats</paper-tab>
|
<paper-tab>Stats</paper-tab>
|
||||||
<paper-tab>Features</paper-tab>
|
<paper-tab>Features</paper-tab>
|
||||||
<paper-tab>Inventory</paper-tab>
|
<paper-tab>Inventory</paper-tab>
|
||||||
Proficiency Bonus
|
|
||||||
<paper-tab>Spellbook</paper-tab>
|
<paper-tab>Spellbook</paper-tab>
|
||||||
<paper-tab>Persona</paper-tab>
|
<paper-tab>Persona</paper-tab>
|
||||||
<paper-tab>Journal</paper-tab>
|
<paper-tab>Journal</paper-tab>
|
||||||
@@ -11,7 +10,7 @@
|
|||||||
|
|
||||||
<core-animated-pages id="tabPages" selected={{selectedTab}} transitions="slide-from-right">
|
<core-animated-pages id="tabPages" selected={{selectedTab}} transitions="slide-from-right">
|
||||||
<swipe-detect touch-action="pan-y">{{> stats}}</swipe-detect>
|
<swipe-detect touch-action="pan-y">{{> stats}}</swipe-detect>
|
||||||
<swipe-detect touch-action="pan-y">features</swipe-detect>
|
<swipe-detect touch-action="pan-y">{{> features}}</swipe-detect>
|
||||||
<swipe-detect touch-action="pan-y">inventory</swipe-detect>
|
<swipe-detect touch-action="pan-y">inventory</swipe-detect>
|
||||||
<swipe-detect touch-action="pan-y">spellBook</swipe-detect>
|
<swipe-detect touch-action="pan-y">spellBook</swipe-detect>
|
||||||
<swipe-detect touch-action="pan-y">persona</swipe-detect>
|
<swipe-detect touch-action="pan-y">persona</swipe-detect>
|
||||||
|
|||||||
32
rpg-docs/client/views/character/features/features.html
Normal file
32
rpg-docs/client/views/character/features/features.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<template name="features">
|
||||||
|
<div class="statsFlex"><!--resources-->
|
||||||
|
{{#if attributeBase "rages"}}
|
||||||
|
{{#statCard id="rages" type="attribute" title="Rages"}}
|
||||||
|
{{attributeValue "rages"}}
|
||||||
|
{{/statCard}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if canCast}}
|
||||||
|
{{#statCard id="spellSlots" type="attribute" title="Spell Slots"}}
|
||||||
|
<h1>{{> spellSlots}}</h1>
|
||||||
|
{{/statCard}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if attributeBase "sorceryPoints"}}
|
||||||
|
{{#statCard id="sorceryPoints" type="attribute" title="Sorcery Points"}}
|
||||||
|
{{attributeValue "sorceryPoints"}}
|
||||||
|
{{/statCard}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if attributeBase "expertiseDice"}}
|
||||||
|
{{#statCard id="expertiseDice" type="attribute" title="Expertise Dice"}}
|
||||||
|
{{attributeValue "expertiseDice"}}
|
||||||
|
{{/statCard}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if attributeBase "superiorityDice"}}
|
||||||
|
{{#statCard id="superiorityDice" type="attribute" title="Superiority Dice"}}
|
||||||
|
{{attributeValue "superiorityDice"}}
|
||||||
|
{{/statCard}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="actionsFlex">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<template name="containerTable">
|
|
||||||
<div>
|
|
||||||
<h3>{{name}}</h3>
|
|
||||||
<table>
|
|
||||||
{{#each items}}
|
|
||||||
{{> itemRow}}
|
|
||||||
{{/each}}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Template.containerTable.helpers({
|
|
||||||
items: function(){
|
|
||||||
return Items.find({container: this._id});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,6 +1,20 @@
|
|||||||
<template name="inventory">
|
<template name="inventory">
|
||||||
<div class="flexItem floatBox">
|
<paper-shadow class="equipment">
|
||||||
<h2>Inventory</h2>
|
Armor: {{#if equippedArmor}}{{equippedArmor}}{{else}}None{{/if}}
|
||||||
{{> inventoryTables}}
|
</paper-shadow>
|
||||||
|
<div class="containers">
|
||||||
|
{{#each containers}}
|
||||||
|
<paper-shadow>
|
||||||
|
<h3>{{name}}</h3>
|
||||||
|
<table>
|
||||||
|
{{#each items}}
|
||||||
|
<tr class={{#if isSelected}}selected{{/if}}>
|
||||||
|
<td>{{#if stackable}}{{quantity}}{{/if}}</td>
|
||||||
|
<td>{{pluralName}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</table>
|
||||||
|
</paper-shadow>
|
||||||
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<template name="inventoryTables">
|
|
||||||
{{#each containers}}
|
|
||||||
{{> containerTable}}
|
|
||||||
{{/each}}
|
|
||||||
</template>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Template.inventoryTables.helpers({
|
|
||||||
containers: function(){
|
|
||||||
return Containers.find({owner: this._id});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
tr.selected{
|
|
||||||
background-color: #4182BC;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<template name="itemRow">
|
|
||||||
<tr class={{#if isSelected}}selected{{/if}}>
|
|
||||||
<td>{{#if stackable}}{{quantity}}{{/if}}</td>
|
|
||||||
<td>{{pluralName}}</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
Template.itemRow.helpers({
|
|
||||||
isSelected: function(){
|
|
||||||
return Session.get('selectedItemRow')=== this._id;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.itemRow.events({
|
|
||||||
"click": function(e){
|
|
||||||
if(Session.get('selectedItemRow')=== this._id){
|
|
||||||
Session.set('selectedItemRow', null);
|
|
||||||
} else{
|
|
||||||
Session.set('selectedItemRow', this._id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -22,6 +22,11 @@
|
|||||||
{{else}}
|
{{else}}
|
||||||
<div class="{{advantage}} skillMod">{{../skillMod skill}}</div>
|
<div class="{{advantage}} skillMod">{{../skillMod skill}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="{{conditionals}} skillName">{{name}}</div>
|
<div class="{{conditionals}} skillName">
|
||||||
|
{{name}}
|
||||||
|
{{#if showPassive}}
|
||||||
|
({{../passiveSkill skill}})
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
//give a character a set of buffs that expire after [duration]
|
|
||||||
pushBuffs = function(id, buffArray, duration){
|
|
||||||
_.each(buffArray, function(buff){
|
|
||||||
var pushObject = {};
|
|
||||||
if(duration > 0){
|
|
||||||
//expiry time is now plus duration
|
|
||||||
var expiry = Characters.findOne(id, {fields: {time: 1}}).time + duration;
|
|
||||||
//ensure the effect has an id
|
|
||||||
buff.effect._id = buff.effect._id || Random.id();
|
|
||||||
//build the expiration object
|
|
||||||
var expiration = {
|
|
||||||
stat: buff.stat,
|
|
||||||
effectId: buff.effect._id,
|
|
||||||
expiry: expiry
|
|
||||||
};
|
|
||||||
//push expiration object to character
|
|
||||||
Characters.update(id, {$push: {expirations: expiration } });
|
|
||||||
}
|
|
||||||
//push the effect to the character
|
|
||||||
pushObject[buff.stat] = buff.effect;
|
|
||||||
Characters.update(id, {$push: pushObject});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//pull all the buffs listed in the buffArray
|
|
||||||
pullBuffs = function(id, buffArray){
|
|
||||||
_.each(buffArray, function(buff){
|
|
||||||
pullEffect(id, buff.effect._id);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//pull a single effect by stat and id
|
|
||||||
pullEffect = function(id, stat, effectId){
|
|
||||||
var pullObject = {};
|
|
||||||
pullObject[stat] = {_id: effectId};
|
|
||||||
Characters.update(id, {$pull: pullObject });
|
|
||||||
}
|
|
||||||
|
|
||||||
//pull an expiry by id
|
|
||||||
pullExpiry = function(id, expiryId){
|
|
||||||
Characters.update(id, {$pull: {expirations: {_id: expiryId} } });
|
|
||||||
}
|
|
||||||
22
rpg-docs/lib/methods/actionUtils.js
Normal file
22
rpg-docs/lib/methods/actionUtils.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Meteor.methods({
|
||||||
|
updateAction: function (charId, oldAction, newAction) {
|
||||||
|
var selector = {_id: charId, "actions._id": oldAction._id};
|
||||||
|
var setter = {"actions.$": newAction};
|
||||||
|
Characters.update(
|
||||||
|
selector,
|
||||||
|
{ $set: setter }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pullAction = function(id, action){
|
||||||
|
var pullObject = {};
|
||||||
|
pullObject["actions"] = {_id: action._id};
|
||||||
|
Characters.update(id, {$pull: pullObject });
|
||||||
|
};
|
||||||
|
|
||||||
|
pushAction = function(id, action){
|
||||||
|
var pushObject = {};
|
||||||
|
pushObject["actions"] = action;
|
||||||
|
Characters.update(id, {$push: pushObject});
|
||||||
|
};
|
||||||
22
rpg-docs/lib/methods/attackUtils.js
Normal file
22
rpg-docs/lib/methods/attackUtils.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Meteor.methods({
|
||||||
|
updateAttack: function (charId, oldAttack, newAttack) {
|
||||||
|
var selector = {_id: charId, "attacks._id": oldAttack._id};
|
||||||
|
var setter = {"attacks.$": newAttack};
|
||||||
|
Characters.update(
|
||||||
|
selector,
|
||||||
|
{ $set: setter }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pullAttack = function(id, attack){
|
||||||
|
var pullObject = {};
|
||||||
|
pullObject["attacks"] = {_id: attack._id};
|
||||||
|
Characters.update(id, {$pull: pullObject });
|
||||||
|
};
|
||||||
|
|
||||||
|
pushAttack = function(id, attack){
|
||||||
|
var pushObject = {};
|
||||||
|
pushObject["attacks"] = attack;
|
||||||
|
Characters.update(id, {$push: pushObject});
|
||||||
|
};
|
||||||
27
rpg-docs/lib/methods/effectUtils.js
Normal file
27
rpg-docs/lib/methods/effectUtils.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Meteor.methods({
|
||||||
|
updateEffect: function (charId, attributeName, effectId, newEffect) {
|
||||||
|
var selector = {_id: charId};
|
||||||
|
selector[attributeName + ".effects._id"] = effectId;
|
||||||
|
var setter = {};
|
||||||
|
setter[attributeName + ".effects.$"] = newEffect
|
||||||
|
Characters.update(
|
||||||
|
selector,
|
||||||
|
{ $set: setter }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//pull a single effect by stat and id
|
||||||
|
pullEffect = function(id, effect){
|
||||||
|
var pullObject = {};
|
||||||
|
pullObject[effect.stat + ".effects"] = {_id: effect._id};
|
||||||
|
Characters.update(id, {$pull: pullObject });
|
||||||
|
}
|
||||||
|
|
||||||
|
pushEffect = function(id, effect){
|
||||||
|
var pushObject = {};
|
||||||
|
pushObject[effect.stat + ".effects"] = effect;
|
||||||
|
Characters.update(id, {$push: pushObject});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
56
rpg-docs/lib/methods/featureUtils.js
Normal file
56
rpg-docs/lib/methods/featureUtils.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
Meteor.methods({
|
||||||
|
addFeature: function(charId, newFeature){
|
||||||
|
Characters.update(
|
||||||
|
charId,
|
||||||
|
{ $push: {"customFeatures": newFeature} }
|
||||||
|
);
|
||||||
|
addFeatureEffects(charId, newFeature);
|
||||||
|
},
|
||||||
|
removeFeature: function(charId, oldFeature){
|
||||||
|
Characters.update(
|
||||||
|
charId,
|
||||||
|
{ $pull: { "customFeatures": {"_id": oldFeature._id} } }
|
||||||
|
);
|
||||||
|
removeFeatureEffects(charId, oldFeature);
|
||||||
|
},
|
||||||
|
updateFeature: function (charId, oldFeature, newFeature) {
|
||||||
|
var selector = {_id: charId, "customFeatures._id": oldFeature._id};
|
||||||
|
var setter = {"customFeatures.$": newFeature};
|
||||||
|
Characters.update(
|
||||||
|
selector,
|
||||||
|
{ $set: setter }
|
||||||
|
);
|
||||||
|
removeFeatureEffects(charId, oldFeature);
|
||||||
|
addFeatureEffects(charId, newFeature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFeatureEffects = function(charId, newFeature){
|
||||||
|
_.each(newFeature.effects, function(effect){
|
||||||
|
pushEffect(charId, effect);
|
||||||
|
});
|
||||||
|
_.each(newFeature.actions, function(action){
|
||||||
|
pushAction(charId, action);
|
||||||
|
});
|
||||||
|
_.each(newFeature.attacks, function(attack){
|
||||||
|
pushAttack(charId, attack);
|
||||||
|
});
|
||||||
|
_.each(newFeature.spells, function(spell){
|
||||||
|
pushSpell(charId, spell);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFeatureEffects = function(charId, oldFeature){
|
||||||
|
_.each(oldFeature.effects, function(effect){
|
||||||
|
pullEffect(charId, effect);
|
||||||
|
});
|
||||||
|
_.each(oldFeature.actions, function(action){
|
||||||
|
pullAction(charId, action);
|
||||||
|
});
|
||||||
|
_.each(newFeature.attacks, function(attack){
|
||||||
|
pushAttack(charId, attack);
|
||||||
|
});
|
||||||
|
_.each(newFeature.spells, function(spell){
|
||||||
|
pushSpell(charId, spell);
|
||||||
|
});
|
||||||
|
};
|
||||||
22
rpg-docs/lib/methods/spellUtils.js
Normal file
22
rpg-docs/lib/methods/spellUtils.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Meteor.methods({
|
||||||
|
updateSpell: function (charId, oldSpell, newSpell) {
|
||||||
|
var selector = {_id: charId, "spells._id": oldSpell._id};
|
||||||
|
var setter = {"spells.$": newSpell};
|
||||||
|
Characters.update(
|
||||||
|
selector,
|
||||||
|
{ $set: setter }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pullSpell = function(id, spell){
|
||||||
|
var pullObject = {};
|
||||||
|
pullObject["spells"] = {_id: spell._id};
|
||||||
|
Characters.update(id, {$pull: pullObject });
|
||||||
|
};
|
||||||
|
|
||||||
|
pushSpell = function(id, spell){
|
||||||
|
var pushObject = {};
|
||||||
|
pushObject["spells"] = spell;
|
||||||
|
Characters.update(id, {$push: pushObject});
|
||||||
|
};
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
Meteor.methods({
|
|
||||||
updateEffect: function (charId, attributeName, effectId, newEffect) {
|
|
||||||
var selector = {_id: charId};
|
|
||||||
selector[attributeName + ".effects._id"] = effectId;
|
|
||||||
var setter = {};
|
|
||||||
setter[attributeName + ".effects.$"] = newEffect
|
|
||||||
Characters.update(
|
|
||||||
selector,
|
|
||||||
{ $set: setter }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
[[[[[ ~/workspace/rpg-docs ]]]]]
|
|
||||||
|
|
||||||
=> Started proxy.
|
|
||||||
=> Started MongoDB.
|
|
||||||
[34mI20141122-15:44:13.239(0)? [39m** You've set up some data subscriptions with Meteor.publish(), but
|
|
||||||
[34mI20141122-15:44:13.351(0)? [39m** you still have autopublish turned on. Because autopublish is still
|
|
||||||
[34mI20141122-15:44:13.352(0)? [39m** on, your Meteor.publish() calls won't have much effect. All data
|
|
||||||
[34mI20141122-15:44:13.352(0)? [39m** will still be sent to all clients.
|
|
||||||
[34mI20141122-15:44:13.352(0)? [39m**
|
|
||||||
[34mI20141122-15:44:13.352(0)? [39m** Turn off autopublish by removing the autopublish package:
|
|
||||||
[34mI20141122-15:44:13.353(0)? [39m**
|
|
||||||
[34mI20141122-15:44:13.353(0)? [39m** $ meteor remove autopublish
|
|
||||||
[34mI20141122-15:44:13.353(0)? [39m**
|
|
||||||
[34mI20141122-15:44:13.353(0)? [39m** .. and make sure you have Meteor.publish() and Meteor.subscribe() calls
|
|
||||||
[34mI20141122-15:44:13.353(0)? [39m** for each collection that you want clients to see.
|
|
||||||
[34mI20141122-15:44:13.353(0)? [39m
|
|
||||||
=> Started your app.
|
|
||||||
|
|
||||||
=> App running at: http://localhost:3000/
|
|
||||||
Can't listen on port 3000. Perhaps another Meteor is running?
|
|
||||||
|
|
||||||
Running two copies of Meteor in the same application directory
|
|
||||||
will not work. If something else is using port 3000, you can
|
|
||||||
specify an alternative port with --port <port>.
|
|
||||||
Can't listen on port 3000. Perhaps another Meteor is running?
|
|
||||||
|
|
||||||
Running two copies of Meteor in the same application directory
|
|
||||||
will not work. If something else is using port 3000, you can
|
|
||||||
specify an alternative port with --port <port>.
|
|
||||||
BIN
rpg-docs/public/jpg/rusted-metal-armor.jpg
Normal file
BIN
rpg-docs/public/jpg/rusted-metal-armor.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Reference in New Issue
Block a user