Implemented Features and Items granting effects, actions, attacks and spells
This commit is contained in:
23
README.md
23
README.md
@@ -1,13 +1,11 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
Strip the core interaction out of swipe-pages to create an element that just listens to swipe events
|
||||
|
||||
wishlist:
|
||||
|
||||
* swipes are emitted as an event if possible
|
||||
* swiping should translate the element
|
||||
* it should bounce back to its resting position when released
|
||||
* 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
|
||||
=============
|
||||
@@ -48,8 +46,13 @@ Packages used
|
||||
* 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)
|
||||
|
||||
************
|
||||
|
||||
To Speed up builds when you know you wont need online package checking use
|
||||
METEOR_OFFLINE_CATALOG=1
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
[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-password@1.0.4
|
||||
accounts-ui-unstyled@1.1.4
|
||||
accounts-ui@1.1.3
|
||||
aldeed:autoform@4.1.0
|
||||
aldeed:collection2@2.2.0
|
||||
accounts-base@1.1.3
|
||||
accounts-password@1.0.5
|
||||
accounts-ui@1.1.4
|
||||
accounts-ui-unstyled@1.1.5
|
||||
aldeed:autoform@4.2.2
|
||||
aldeed:collection2@2.3.0
|
||||
aldeed:simple-schema@1.1.0
|
||||
application-configuration@1.0.3
|
||||
autoupdate@1.1.3
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.3
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
application-configuration@1.0.4
|
||||
autoupdate@1.1.4
|
||||
base64@1.0.2
|
||||
binary-heap@1.0.2
|
||||
blaze@2.0.4
|
||||
blaze-tools@1.0.2
|
||||
boilerplate-generator@1.0.2
|
||||
callback-hook@1.0.2
|
||||
check@1.0.3
|
||||
cw4gn3r:jquery-event-drag@2.2.0
|
||||
dburles:collection-helpers@1.0.1
|
||||
ddp@1.0.12
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
email@1.0.4
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.8
|
||||
id-map@1.0.1
|
||||
insecure@1.0.1
|
||||
iron:controller@1.0.3
|
||||
iron:core@1.0.3
|
||||
iron:dynamic-template@1.0.3
|
||||
iron:layout@1.0.3
|
||||
iron:location@1.0.3
|
||||
iron:middleware-stack@1.0.3
|
||||
iron:router@1.0.3
|
||||
iron:url@1.0.3
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
launch-screen@1.0.0
|
||||
less@1.0.11
|
||||
livedata@1.0.11
|
||||
localstorage@1.0.1
|
||||
logging@1.0.5
|
||||
meteor-platform@1.2.0
|
||||
meteor@1.1.3
|
||||
minifiers@1.1.2
|
||||
minimongo@1.0.5
|
||||
mobile-status-bar@1.0.1
|
||||
mongo-livedata@1.0.6
|
||||
mongo@1.0.9
|
||||
mrt:moment@2.6.0
|
||||
dburles:collection-helpers@1.0.2
|
||||
ddp@1.0.13
|
||||
deps@1.0.6
|
||||
ejson@1.0.5
|
||||
email@1.0.5
|
||||
fastclick@1.0.2
|
||||
follower-livedata@1.0.3
|
||||
geojson-utils@1.0.2
|
||||
html-tools@1.0.3
|
||||
htmljs@1.0.3
|
||||
http@1.0.9
|
||||
id-map@1.0.2
|
||||
insecure@1.0.2
|
||||
iron:controller@1.0.6
|
||||
iron:core@1.0.6
|
||||
iron:dynamic-template@1.0.6
|
||||
iron:layout@1.0.6
|
||||
iron:location@1.0.6
|
||||
iron:middleware-stack@1.0.6
|
||||
iron:router@1.0.6
|
||||
iron:url@1.0.6
|
||||
jquery@1.0.2
|
||||
json@1.0.2
|
||||
launch-screen@1.0.1
|
||||
less@1.0.12
|
||||
livedata@1.0.12
|
||||
localstorage@1.0.2
|
||||
logging@1.0.6
|
||||
meteor@1.1.4
|
||||
meteor-platform@1.2.1
|
||||
minifiers@1.1.3
|
||||
minimongo@1.0.6
|
||||
mobile-status-bar@1.0.2
|
||||
momentjs:moment@2.8.4
|
||||
mongo@1.0.11
|
||||
npm-bcrypt@0.7.7
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
service-configuration@1.0.2
|
||||
session@1.0.4
|
||||
sha@1.0.1
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
srp@1.0.1
|
||||
templating@1.0.9
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.2
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.4
|
||||
observe-sequence@1.0.4
|
||||
ordered-dict@1.0.2
|
||||
random@1.0.2
|
||||
reactive-dict@1.0.5
|
||||
reactive-var@1.0.4
|
||||
reload@1.1.2
|
||||
retry@1.0.2
|
||||
routepolicy@1.0.3
|
||||
service-configuration@1.0.3
|
||||
session@1.0.5
|
||||
sha@1.0.2
|
||||
spacebars@1.0.4
|
||||
spacebars-compiler@1.0.4
|
||||
srp@1.0.2
|
||||
templating@1.0.10
|
||||
tracker@1.0.4
|
||||
ui@1.0.5
|
||||
underscore@1.0.2
|
||||
url@1.0.3
|
||||
webapp@1.1.5
|
||||
webapp-hashing@1.0.2
|
||||
|
||||
@@ -37,7 +37,7 @@ Schemas.Character = new SimpleSchema({
|
||||
"proficiencyBonus.effects": {
|
||||
type: [Schemas.Effect],
|
||||
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},
|
||||
@@ -68,6 +68,8 @@ Schemas.Character = new SimpleSchema({
|
||||
superiorityDice: {type: Schemas.Attribute},
|
||||
expertiseDice: {type: Schemas.Attribute},
|
||||
|
||||
//specific features
|
||||
rageDamage: {type: Schemas.Attribute},
|
||||
|
||||
//hit dice
|
||||
d6HitDice: {type: Schemas.Attribute},
|
||||
@@ -174,52 +176,24 @@ Schemas.Character = new SimpleSchema({
|
||||
|
||||
strengthAttack: {type: Schemas.Skill},
|
||||
"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.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.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.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.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.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.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.ability": { type: String, defaultValue: "dexterity" },
|
||||
@@ -239,19 +213,22 @@ Schemas.Character = new SimpleSchema({
|
||||
},
|
||||
|
||||
//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 },
|
||||
time: { type: Number, min: 0, decimal: true, defaultValue: 0},
|
||||
initiativeOrder:{ type: Number, min: 0, max: 1, decimal: true, defaultValue: 0},
|
||||
expirations: { type: [Schemas.Expiration], defaultValue: []},
|
||||
spells: { type: [Schemas.Spell], defaultValue: []}
|
||||
buffs: { type: [Schemas.Buff], defaultValue: []}
|
||||
//TODO add permission stuff for owner, readers and writers
|
||||
//TODO add per-character settings
|
||||
});
|
||||
|
||||
Characters.attachSchema(Schemas.Character);
|
||||
|
||||
//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({
|
||||
changed: function(character){
|
||||
var currentTime = character.time;
|
||||
@@ -276,25 +253,38 @@ Characters.find({},{fields: {time: 1, expirations: 1, features: 1}}).observe({
|
||||
});
|
||||
|
||||
var attributeBase = function(charId, attribute){
|
||||
var effects = _.groupBy(attribute.effects, "operation");
|
||||
var value = 0;
|
||||
_.each(attribute.effects, function(effect){
|
||||
switch(effect.operation) {
|
||||
case "add":
|
||||
value += evaluateEffect(charId, effect);
|
||||
break;
|
||||
case "mul":
|
||||
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;
|
||||
|
||||
//start with the highest base value
|
||||
_.each(effects.base, function(effect){
|
||||
var efv = evaluateEffect(charId, effect)
|
||||
if (effect.value > value){
|
||||
value = effect.value;
|
||||
}
|
||||
});
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
@@ -309,7 +299,7 @@ Characters.helpers({
|
||||
fieldSelector[fieldName] = 1;
|
||||
var char = Characters.findOne(this._id, {fields: fieldSelector});
|
||||
var field = char[fieldName];
|
||||
if(!field){
|
||||
if(field === undefined){
|
||||
throw new Meteor.Error("getField failed",
|
||||
"getField could not find field " + fieldName + " in character "+ char._id);
|
||||
}
|
||||
@@ -333,35 +323,15 @@ Characters.helpers({
|
||||
return this.getField(fieldName);
|
||||
},
|
||||
|
||||
attributeValue: (function(){
|
||||
//store a private array of attributes we've visited without returning
|
||||
//if we try to visit the same attribute twice before resolving its value
|
||||
//we are in a dependency loop and need to GTFO
|
||||
var visitedAttributes = [];
|
||||
return function(attributeName){
|
||||
check(attributeName, String);
|
||||
//we're still evaluating this attribute, must be in a loop
|
||||
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;
|
||||
}
|
||||
})(),
|
||||
attributeValue: function(attributeName){
|
||||
var charId = this._id;
|
||||
var attribute = this.getField(attributeName);
|
||||
//base value
|
||||
var value = this.attributeBase(attributeName);
|
||||
//plus adjustment
|
||||
value += attribute.adjustment;
|
||||
return value;
|
||||
},
|
||||
|
||||
attributeBase: (function(){
|
||||
//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
|
||||
*/
|
||||
Schemas.Effect = new SimpleSchema({
|
||||
@@ -16,7 +16,7 @@ Schemas.Effect = new SimpleSchema({
|
||||
operation: {
|
||||
type: String,
|
||||
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: {
|
||||
type: Number,
|
||||
@@ -32,5 +32,10 @@ Schemas.Effect = new SimpleSchema({
|
||||
type: String,
|
||||
defaultValue: "editable",
|
||||
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},
|
||||
"components.verbal": {type: Boolean},
|
||||
"components.somatic": {type: Boolean},
|
||||
"components.material": {type: String},
|
||||
"components.material": {type: String, optional: true},
|
||||
"components.concentration": {type: Boolean},
|
||||
buffs: {type: [Schemas.Buff], optional: true},
|
||||
ritual: {type: Boolean},
|
||||
selfBuffs: {type: [Schemas.Buff], defaultValue: []},
|
||||
level: {type: Number},
|
||||
class: {type: String}
|
||||
});
|
||||
@@ -4,18 +4,42 @@ Schemas.Item = new SimpleSchema({
|
||||
name: {type: String, defaultValue: "New Item"},
|
||||
plural: {type: String, optional: true},
|
||||
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},
|
||||
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
tradeGood: {type: Boolean, defaultValue: false},
|
||||
stackable: {type: Boolean, defaultValue: false},
|
||||
buffs: {type: [Schemas.Buff], defaultValue: []},
|
||||
equipmentSlot: {type: String, defaultValue: "", allowedValues: ["head", "body", "arms", "hands", "held", "feet"]},
|
||||
feature: {type: Schemas.Feature},
|
||||
equipmentSlot: {
|
||||
type: String,
|
||||
defaultValue: "none",
|
||||
allowedValues: ["none", "head", "armor", "arms", "hands", "held", "feet"]
|
||||
},
|
||||
equipped: {type: Boolean, defaultValue: false}
|
||||
});
|
||||
|
||||
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({
|
||||
totalValue: function(){
|
||||
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 {
|
||||
width: 148px;
|
||||
margin: 4px;
|
||||
padding: 16px;
|
||||
font-size: 14px;
|
||||
@@ -67,7 +66,7 @@ paper-button {
|
||||
}
|
||||
|
||||
.card.double {
|
||||
width: 304px;
|
||||
width: 332px;
|
||||
}
|
||||
|
||||
.card paper-button {
|
||||
|
||||
@@ -31,7 +31,7 @@ h1, .headline {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
flex-grow: 1;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
#stats .abilityFlex{
|
||||
@@ -25,6 +26,26 @@
|
||||
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 > * {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
@@ -35,6 +56,14 @@
|
||||
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 {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
|
||||
@@ -4,73 +4,6 @@
|
||||
<div class="abilityFlex">
|
||||
{{> abilityCards}}
|
||||
</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 id="detailContainer">
|
||||
<div cross-fade id="darkOverlay"></div>
|
||||
@@ -80,12 +13,6 @@
|
||||
</core-animated-pages>
|
||||
</template>
|
||||
|
||||
<template name="hitDice">
|
||||
{{# if ../attributeBase hitDice}}
|
||||
{{../attributeValue hitDice}}d{{d}} + {{../abilityMod "constitution"}}
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
<template name="spellSlots">
|
||||
{{attributeValue "level1SpellSlots"}}
|
||||
{{attributeValue "level2SpellSlots"}}
|
||||
@@ -98,6 +25,17 @@
|
||||
{{attributeValue "level9SpellSlots"}}
|
||||
</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">
|
||||
<!--needs character, attributeName, attributeTitle-->
|
||||
{{#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({
|
||||
attributeTitle: function(){
|
||||
return Session.get("selectedAttributeTitle");
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
background-color: #D50000;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
.abilityFlex .card {
|
||||
@@ -20,10 +21,11 @@
|
||||
|
||||
.abilityCardRight {
|
||||
flex-grow: 1;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.abilityCardRight hr{
|
||||
margin: 8px -16px;
|
||||
margin: 8px 0 8px -16px;
|
||||
}
|
||||
|
||||
.abilityCardRight h1{
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<div class="abilityCardRight">
|
||||
<h1>Dexterity</h1>
|
||||
{{> skillRow name="Save" skill="dexteritySave"}}
|
||||
{{> skillRow name="Initiative" skill="initiative"}}
|
||||
<hr>
|
||||
{{> skillRow name="Acrobatics" skill="acrobatics"}}
|
||||
{{> skillRow name="Sleight of Hand" skill="sleightOfHand"}}
|
||||
@@ -52,6 +53,18 @@
|
||||
<h1>Constitution</h1>
|
||||
{{> skillRow name="Save" skill="constitutionSave"}}
|
||||
<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>
|
||||
</paper-shadow>
|
||||
</template>
|
||||
@@ -90,7 +103,7 @@
|
||||
{{> skillRow name="Animal Handling" skill="animalHandling"}}
|
||||
{{> skillRow name="Insight" skill="insight"}}
|
||||
{{> skillRow name="Medicine" skill="medicine"}}
|
||||
{{> skillRow name="Perception" skill="perception"}}
|
||||
{{> skillRow name="Perception" skill="perception" showPassive="true"}}
|
||||
{{> skillRow name="Survival" skill="survival"}}
|
||||
</div>
|
||||
</paper-shadow>
|
||||
@@ -114,3 +127,9 @@
|
||||
</div>
|
||||
</paper-shadow>
|
||||
</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>Features</paper-tab>
|
||||
<paper-tab>Inventory</paper-tab>
|
||||
Proficiency Bonus
|
||||
<paper-tab>Spellbook</paper-tab>
|
||||
<paper-tab>Persona</paper-tab>
|
||||
<paper-tab>Journal</paper-tab>
|
||||
@@ -11,7 +10,7 @@
|
||||
|
||||
<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">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">spellBook</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">
|
||||
<div class="flexItem floatBox">
|
||||
<h2>Inventory</h2>
|
||||
{{> inventoryTables}}
|
||||
<paper-shadow class="equipment">
|
||||
Armor: {{#if equippedArmor}}{{equippedArmor}}{{else}}None{{/if}}
|
||||
</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>
|
||||
</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}}
|
||||
<div class="{{advantage}} skillMod">{{../skillMod skill}}</div>
|
||||
{{/if}}
|
||||
<div class="{{conditionals}} skillName">{{name}}</div>
|
||||
<div class="{{conditionals}} skillName">
|
||||
{{name}}
|
||||
{{#if showPassive}}
|
||||
({{../passiveSkill skill}})
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</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