Gave effects their own collection, they no longer live in arrays attached to skills/attributes
Also improved the display of features and generally iterated on their manipulation. Characters now fetch the relevant effects directly when making a calculation, simplifying almost everything. Effects now store a reference to their source if they have one. Effect names are now optional, they can be fetched from the source's name if the source exists.
This commit is contained in:
@@ -1 +1 @@
|
||||
METEOR@1.0.2.1
|
||||
METEOR@1.0.3.1
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
accounts-base@1.1.3
|
||||
accounts-password@1.0.5
|
||||
accounts-password@1.0.6
|
||||
accounts-ui@1.1.4
|
||||
accounts-ui-unstyled@1.1.5
|
||||
accounts-ui-unstyled@1.1.6
|
||||
aldeed:autoform@4.2.2
|
||||
aldeed:collection2@2.3.1
|
||||
aldeed:simple-schema@1.1.0
|
||||
application-configuration@1.0.4
|
||||
autoupdate@1.1.4
|
||||
autoupdate@1.1.5
|
||||
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
|
||||
check@1.0.4
|
||||
conielo:autoform-polymer-paper@0.1.1
|
||||
cw4gn3r:jquery-event-drag@2.2.0
|
||||
dburles:collection-helpers@1.0.2
|
||||
ddp@1.0.13
|
||||
ddp@1.0.14
|
||||
deps@1.0.6
|
||||
differential:vulcanize@0.0.3
|
||||
ejson@1.0.5
|
||||
@@ -27,18 +27,18 @@ follower-livedata@1.0.3
|
||||
geojson-utils@1.0.2
|
||||
html-tools@1.0.3
|
||||
htmljs@1.0.3
|
||||
http@1.0.9
|
||||
http@1.0.10
|
||||
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
|
||||
iron:controller@1.0.7
|
||||
iron:core@1.0.7
|
||||
iron:dynamic-template@1.0.7
|
||||
iron:layout@1.0.7
|
||||
iron:location@1.0.7
|
||||
iron:middleware-stack@1.0.7
|
||||
iron:router@1.0.7
|
||||
iron:url@1.0.7
|
||||
jquery@1.11.3
|
||||
json@1.0.2
|
||||
launch-screen@1.0.1
|
||||
less@1.0.12
|
||||
@@ -60,17 +60,17 @@ reactive-dict@1.0.5
|
||||
reactive-var@1.0.4
|
||||
reload@1.1.2
|
||||
retry@1.0.2
|
||||
routepolicy@1.0.3
|
||||
routepolicy@1.0.4
|
||||
service-configuration@1.0.3
|
||||
session@1.0.5
|
||||
sha@1.0.2
|
||||
spacebars@1.0.4
|
||||
spacebars@1.0.5
|
||||
spacebars-compiler@1.0.4
|
||||
srp@1.0.2
|
||||
templating@1.0.10
|
||||
tracker@1.0.4
|
||||
templating@1.0.11
|
||||
tracker@1.0.5
|
||||
ui@1.0.5
|
||||
underscore@1.0.2
|
||||
url@1.0.3
|
||||
webapp@1.1.5
|
||||
webapp@1.1.6
|
||||
webapp-hashing@1.0.2
|
||||
|
||||
@@ -17,40 +17,22 @@ Schemas.Character = new SimpleSchema({
|
||||
|
||||
//attributes
|
||||
//ability scores
|
||||
strength: {type: Schemas.Attribute},
|
||||
dexterity: {type: Schemas.Attribute},
|
||||
constitution: {type: Schemas.Attribute},
|
||||
intelligence: {type: Schemas.Attribute},
|
||||
wisdom: {type: Schemas.Attribute},
|
||||
charisma: {type: Schemas.Attribute},
|
||||
strength: {type: Schemas.Attribute},
|
||||
dexterity: {type: Schemas.Attribute},
|
||||
constitution: {type: Schemas.Attribute},
|
||||
intelligence: {type: Schemas.Attribute},
|
||||
wisdom: {type: Schemas.Attribute},
|
||||
charisma: {type: Schemas.Attribute},
|
||||
|
||||
//stats
|
||||
hitPoints: {type: Schemas.Attribute},
|
||||
"hitPoints.effects": {
|
||||
type: [Schemas.Effect],
|
||||
defaultValue: [
|
||||
{name: "Constitution modifier for each level", calculation: "level * constitutionMod", operation: "add", type: "inate"}
|
||||
]
|
||||
},
|
||||
experience: {type: Schemas.Attribute},
|
||||
proficiencyBonus: {type: Schemas.Attribute},
|
||||
"proficiencyBonus.effects": {
|
||||
type: [Schemas.Effect],
|
||||
defaultValue: [
|
||||
{name: "Proficiency bonus by level", calculation: "floor(level / 4 + 1.75)", operation: "add", type: "inate"}
|
||||
]
|
||||
},
|
||||
speed: {type: Schemas.Attribute},
|
||||
weight: {type: Schemas.Attribute},
|
||||
age: {type: Schemas.Attribute},
|
||||
ageRate: {type: Schemas.Attribute},
|
||||
armor: {type: Schemas.Attribute},
|
||||
"armor.effects": {
|
||||
type: [Schemas.Effect],
|
||||
defaultValue: [
|
||||
{name: "Dexterity Modifier", calculation: "dexterityArmor", operation: "add", type: "inate"}
|
||||
]
|
||||
},
|
||||
hitPoints: {type: Schemas.Attribute},
|
||||
experience: {type: Schemas.Attribute},
|
||||
proficiencyBonus: {type: Schemas.Attribute},
|
||||
speed: {type: Schemas.Attribute},
|
||||
weight: {type: Schemas.Attribute},
|
||||
age: {type: Schemas.Attribute},
|
||||
ageRate: {type: Schemas.Attribute},
|
||||
armor: {type: Schemas.Attribute},
|
||||
|
||||
//resources
|
||||
level1SpellSlots: {type: Schemas.Attribute},
|
||||
@@ -199,61 +181,52 @@ Schemas.Character = new SimpleSchema({
|
||||
"dexterityArmor.ability": { type: String, defaultValue: "dexterity" },
|
||||
|
||||
//proficiencies
|
||||
weaponsProficiencies: {
|
||||
type: [Schemas.Proficiency],
|
||||
defaultValue: []
|
||||
},
|
||||
toolsProficiencies: {
|
||||
type: [Schemas.Proficiency],
|
||||
defaultValue: []
|
||||
},
|
||||
languages: {
|
||||
type: [Schemas.Proficiency],
|
||||
defaultValue: []
|
||||
},
|
||||
weaponsProficiencies: { type: [Schemas.Proficiency], defaultValue: [] },
|
||||
toolsProficiencies: { type: [Schemas.Proficiency], defaultValue: [] },
|
||||
languages: { type: [Schemas.Proficiency], defaultValue: [] },
|
||||
|
||||
//mechanics
|
||||
actions: { type: [Schemas.Action], defaultValue: []},
|
||||
deathSave: { type: Schemas.DeathSave },
|
||||
time: { type: Number, min: 0, decimal: true, defaultValue: 0},
|
||||
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},
|
||||
buffs: { type: [Schemas.Buff], 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
|
||||
//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;
|
||||
_.each(character.expirations, function(expiration){
|
||||
if(expiration.expiry <= currentTime){
|
||||
var charId = character._id;
|
||||
var stat = expiration.stat;
|
||||
//remove expired effects
|
||||
_.each(expiration.effectIds, function(effectId){
|
||||
pullEffect(charId, stat, effectId);
|
||||
});
|
||||
//disable expired features
|
||||
_.each(expiration.featureIds, function(featureId){
|
||||
var feature = Characters.findOne({_id: charId, "features._id": featureId}, {fields: {features: 1}}).features[0];
|
||||
feature.enabled = false;
|
||||
Characters.update({_id: charId, "features._id": featureId}, {$set: {"features.$": feature}});
|
||||
});
|
||||
pullExpiry(charId, expiration._id);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
//TODO on creating a new character, these effects need to be set up
|
||||
/*
|
||||
"hitPoints.effects": {
|
||||
type: [Schemas.Effect],
|
||||
defaultValue: [
|
||||
{name: "Constitution modifier for each level", calculation: "level * constitutionMod", operation: "add", type: "inate"}
|
||||
]
|
||||
},
|
||||
"proficiencyBonus.effects": {
|
||||
type: [Schemas.Effect],
|
||||
defaultValue: [
|
||||
{name: "Proficiency bonus by level", calculation: "floor(level / 4 + 1.75)", operation: "add", type: "inate"}
|
||||
]
|
||||
},
|
||||
"armor.effects": {
|
||||
type: [Schemas.Effect],
|
||||
defaultValue: [
|
||||
{name: "Dexterity Modifier", calculation: "dexterityArmor", operation: "add", type: "inate"}
|
||||
]
|
||||
},
|
||||
{type: "inate", name: "Resistance doesn't stack", operation: "min", value: 0.5},
|
||||
{type: "inate", name: "Vulnerability doesn't stack", operation: "max", value: 2}
|
||||
*/
|
||||
|
||||
var attributeBase = function(charId, attribute){
|
||||
var effects = _.groupBy(attribute.effects, "operation");
|
||||
var attributeBase = function(charId, statName){
|
||||
check(statName, String);
|
||||
var effects = Effects.find({charId: charId, stat: statName}).fetch();
|
||||
effects = _.groupBy(effects, "operation");
|
||||
var value = 0;
|
||||
|
||||
|
||||
//start with the highest base value
|
||||
_.each(effects.base, function(effect){
|
||||
var efv = evaluateEffect(charId, effect)
|
||||
@@ -261,23 +234,23 @@ var attributeBase = function(charId, attribute){
|
||||
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);
|
||||
@@ -348,9 +321,8 @@ Characters.helpers({
|
||||
visitedAttributes.push(attributeName);
|
||||
try{
|
||||
var charId = this._id;
|
||||
var attribute = this.getField(attributeName);
|
||||
//base value
|
||||
var value = attributeBase(charId, attribute);
|
||||
var value = attributeBase(charId, attributeName);
|
||||
}finally{
|
||||
//this attribute returns or fails, pull it from the array, we may visit it again safely
|
||||
visitedAttributes = _.without(visitedAttributes, attributeName);
|
||||
@@ -388,8 +360,7 @@ Characters.helpers({
|
||||
|
||||
//add multiplied proficiency bonus to modifier
|
||||
mod += prof * this.attributeValue("proficiencyBonus");
|
||||
|
||||
_.each(skill.effects, function(effect){
|
||||
Effects.find({charId: charId, stat: skillName}).forEach(function(effect){
|
||||
switch(effect.operation) {
|
||||
case "add":
|
||||
mod += evaluateEffect(charId, effect);
|
||||
@@ -415,14 +386,11 @@ Characters.helpers({
|
||||
}
|
||||
})(),
|
||||
|
||||
proficiency: function(skill){
|
||||
if (_.isString(skill)){
|
||||
skill = this.getField(skill);
|
||||
}
|
||||
proficiency: function(skillName){
|
||||
var charId = this._id;
|
||||
//return largest value in proficiency array
|
||||
var prof = 0;
|
||||
_.each(skill.effects, function(effect){
|
||||
Effects.find({charId: charId, stat: skillName}).forEach(function(effect){
|
||||
if(effect.operation === "proficiency"){
|
||||
var newProf = evaluateEffect(charId, effect);
|
||||
if (newProf > prof){
|
||||
@@ -440,7 +408,7 @@ Characters.helpers({
|
||||
var charId = this._id
|
||||
var mod = +this.skillMod(skillName);
|
||||
var value = 10 + mod;
|
||||
_.each(skill.effects, function(effect){
|
||||
Effects.find({charId: charId, stat: skillName}).forEach(function(effect){
|
||||
if(effect.operation === "passiveAdd"){
|
||||
value += evaluateEffect(charId, effect);
|
||||
}
|
||||
|
||||
49
rpg-docs/Model/Character/Effects.js
Normal file
49
rpg-docs/Model/Character/Effects.js
Normal file
@@ -0,0 +1,49 @@
|
||||
Effects = new Meteor.Collection("effects");
|
||||
|
||||
/*
|
||||
* Effects are reason-value attached to skills and abilities
|
||||
* that modify their final value or presentation in some way
|
||||
*/
|
||||
Schemas.Effect = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
optional: true //TODO make necessary if there is no owner
|
||||
},
|
||||
operation: {
|
||||
type: String,
|
||||
defaultValue: "add",
|
||||
allowedValues: ["base", "proficiency","add","mul","min","max","advantage","disadvantage","passiveAdd","fail","conditional"]
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
},
|
||||
calculation: {
|
||||
type: String,
|
||||
optional: true
|
||||
},
|
||||
//indicates what the effect originated from
|
||||
type: {
|
||||
type: String,
|
||||
defaultValue: "editable",
|
||||
allowedValues: ["editable", "feature", "buff", "equipment", "inate"]
|
||||
},
|
||||
//the id of the feature, buff or item that created this effect
|
||||
sourceId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
optional: true
|
||||
},
|
||||
//which stat the effect is applied to
|
||||
stat: {
|
||||
type: String,
|
||||
optional: true
|
||||
}
|
||||
});
|
||||
|
||||
Effects.attachSchema(Schemas.Effect);
|
||||
@@ -1,35 +1,12 @@
|
||||
Features = new Meteor.Collection("features");
|
||||
|
||||
Schemas.Feature = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
name: {type: String},
|
||||
description:{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);
|
||||
|
||||
//update the features of the items as needed
|
||||
Features.find({}, {fields: {name: 0, description: 0}}).observe({
|
||||
added: function(newFeature){
|
||||
if(newFeature.charId){
|
||||
//make sure existing versions of this feature's effects aren't duplicated
|
||||
removeFeatureEffects(newFeature.charId, newFeature);
|
||||
//add the new feature's effects
|
||||
addFeatureEffects(newFeature.charId, newFeature);
|
||||
}
|
||||
},
|
||||
changed: function(newFeature, oldFeature){
|
||||
if(oldFeature.charId)
|
||||
removeFeatureEffects(oldFeature.charId, oldFeature);
|
||||
if(newFeature.charId)
|
||||
addFeatureEffects(newFeature.charId, newFeature);
|
||||
},
|
||||
removed: function(oldFeature){
|
||||
if(oldFeature.charId)
|
||||
removeFeatureEffects(oldFeature.charId, oldFeature);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,8 +5,6 @@ Schemas.Attribute = new SimpleSchema({
|
||||
type: Number,
|
||||
defaultValue: 0
|
||||
},
|
||||
//effect arrays
|
||||
effects: { type: [Schemas.Effect], defaultValue: [] },
|
||||
reset: {
|
||||
type: String,
|
||||
defaultValue: "longRest",
|
||||
@@ -21,14 +19,6 @@ Schemas.Vulnerability = new SimpleSchema({
|
||||
type: Number,
|
||||
defaultValue: 0
|
||||
},
|
||||
//effect arrays
|
||||
effects: {
|
||||
type: [Schemas.Effect],
|
||||
defaultValue: [
|
||||
{type: "inate", name: "Resistance doesn't stack", operation: "min", value: 0.5},
|
||||
{type: "inate", name: "Vulnerability doesn't stack", operation: "max", value: 2}
|
||||
]
|
||||
},
|
||||
reset: {
|
||||
type: String,
|
||||
defaultValue: "longRest",
|
||||
|
||||
@@ -8,10 +8,6 @@ Schemas.Buff = new SimpleSchema({
|
||||
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,4 @@
|
||||
Schemas.Skill = new SimpleSchema({
|
||||
//attribute name that this skill used as base mod for roll
|
||||
ability: { type: String, defaultValue: "" },
|
||||
effects: { type: [Schemas.Effect], defaultValue: [] },
|
||||
});
|
||||
@@ -11,13 +11,6 @@ Schemas.Item = new SimpleSchema({
|
||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
tradeGood: {type: Boolean, defaultValue: false},
|
||||
stackable: {type: Boolean, defaultValue: false},
|
||||
feature: {type: Schemas.Feature},
|
||||
"feature.name": {type: String, autoValue: function(){return this.field("name").value}},
|
||||
"feature.description": {type: String, autoValue: function(){return this.field("description").value}},
|
||||
"feature.source": {type: String, autoValue: function(){return this.field("name").value}},
|
||||
"feature.effects.$.name": {type: String, autoValue: function(){return this.field("name").value}},
|
||||
"feature.effects.$.type": {type: String, autoValue: function(){return "equipment"}},
|
||||
"feature.attacks.$.name": {type: String, autoValue: function(){return this.field("name").value}},
|
||||
equipmentSlot: {
|
||||
type: String,
|
||||
defaultValue: "none",
|
||||
@@ -28,24 +21,6 @@ Schemas.Item = new SimpleSchema({
|
||||
|
||||
Items.attachSchema(Schemas.Item);
|
||||
|
||||
//update the features of the items as needed
|
||||
Items.find({}, {fields: {feature: 1, charId: 1, equipped: 1}}).observe({
|
||||
added: function(newItem){
|
||||
if(newItem.feature && newItem.charId)
|
||||
addFeatureEffects(newItem.charId, newItem.feature);
|
||||
},
|
||||
changed: function(newItem, oldItem){
|
||||
if(oldItem.feature && oldItem.charId)
|
||||
removeFeatureEffects(oldItem.charId, oldItem.feature);
|
||||
if(newItem.feature && newItem.charId)
|
||||
addFeatureEffects(newItem.charId, newItem.feature);
|
||||
},
|
||||
removed: function(oldItem){
|
||||
if(oldItem.feature && oldItem.charId)
|
||||
removeFeatureEffects(oldItem.charId, oldItem.feature);
|
||||
}
|
||||
});
|
||||
|
||||
Items.helpers({
|
||||
totalValue: function(){
|
||||
return this.value * this.quantity;
|
||||
|
||||
@@ -25,6 +25,7 @@ Router.map( function () {
|
||||
Meteor.subscribe("characterContainers", this.params._id, Meteor.userId()),
|
||||
Meteor.subscribe("characterItems", this.params._id, Meteor.userId()),
|
||||
Meteor.subscribe("characterFeatures", this.params._id, Meteor.userId()),
|
||||
Meteor.subscribe("characterEffects", this.params._id, Meteor.userId()),
|
||||
];
|
||||
},
|
||||
data: function() {
|
||||
|
||||
@@ -9,6 +9,14 @@ this.GlobalUI = (function() {
|
||||
toast.text = text;
|
||||
return toast.show();
|
||||
};
|
||||
|
||||
GlobalUI.setDialog = function(opts){
|
||||
this.dialog = $("[global-dialog]")[0];
|
||||
Session.set("global.ui.dialogHeader", opts.heading);
|
||||
Session.set("global.ui.dialogData", opts.data);
|
||||
Session.set("global.ui.dialogTemplate", opts.template);
|
||||
Session.set("global.ui.dialogFullOnMobile", opts.fullOnMobile != null);
|
||||
};
|
||||
|
||||
GlobalUI.showDialog = function(opts) {
|
||||
this.dialog = $("[global-dialog]")[0];
|
||||
|
||||
@@ -90,6 +90,25 @@ paper-button {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.scroll-y {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.fab-buffer {
|
||||
height: 88px;
|
||||
}
|
||||
|
||||
*[hidden] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
html /deep/ paper-action-dialog[global-dialog] {
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,99 +1,5 @@
|
||||
<template name="stats">
|
||||
<core-animated-pages selected={{selectedSection}} transitions="hero-transition cross-fade" fit style="overflow-y: scroll">
|
||||
<section id="stats">
|
||||
{{> abilityCards}}
|
||||
</section>
|
||||
<section id="detailContainer">
|
||||
<div cross-fade id="darkOverlay"></div>
|
||||
{{> attributeDialog character=this}}
|
||||
{{> skillDialog character=this}}
|
||||
</section>
|
||||
</core-animated-pages>
|
||||
</template>
|
||||
|
||||
<template name="spellSlots">
|
||||
{{attributeValue "level1SpellSlots"}}
|
||||
{{attributeValue "level2SpellSlots"}}
|
||||
{{attributeValue "level3SpellSlots"}}
|
||||
{{attributeValue "level4SpellSlots"}}
|
||||
{{attributeValue "level5SpellSlots"}}
|
||||
{{attributeValue "level6SpellSlots"}}
|
||||
{{attributeValue "level7SpellSlots"}}
|
||||
{{attributeValue "level8SpellSlots"}}
|
||||
{{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}}
|
||||
<paper-shadow id="attributeDialog"
|
||||
class="detailCard"
|
||||
hero-id={{session "selectedAttribute"}}
|
||||
hero
|
||||
heading={{session "selectedAttributeTitle"}}
|
||||
z="2">
|
||||
|
||||
{{character.attributeValue attributeName}}<br>
|
||||
{{#each effects.add}}
|
||||
{{> attributeEffect}}
|
||||
{{/each}}
|
||||
{{#each effects.mul}}
|
||||
{{> attributeEffect}}
|
||||
{{/each}}
|
||||
{{#each effects.min}}
|
||||
{{> attributeEffect}}
|
||||
{{/each}}
|
||||
{{#each effects.max}}
|
||||
{{> attributeEffect}}
|
||||
{{/each}}
|
||||
{{signedString attribute.adjustment}}
|
||||
</paper-shadow>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
<template name="attributeEffect">
|
||||
{{#if editing}}
|
||||
<div class="editEffect">
|
||||
<paper-dropdown-menu label="Operation">
|
||||
<paper-dropdown layered class="dropdown">
|
||||
<core-menu id="operationSelector" selected={{operationNumber}} class="menu">
|
||||
<paper-item>add</paper-item>
|
||||
<paper-item>multiply</paper-item>
|
||||
<paper-item>min</paper-item>
|
||||
<paper-item>max</paper-item>
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
<paper-input id="effectValueInput" label="Value" value={{value}} floatinglabel></paper-input>
|
||||
<paper-input id="effectNameInput" label="Name" value={{name}} floatinglabel></paper-input>
|
||||
<paper-icon-button id="doneButton" icon="done" title="save" role="button" aria-label="save"></paper-icon-button>
|
||||
<paper-icon-button id="cancelButton" icon="clear" title="cancel" role="button" aria-label="cancel"></paper-icon-button>
|
||||
<paper-icon-button id="deleteButton" icon="delete" title="delete" role="button" aria-label="delete"></paper-icon-button>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="effect">
|
||||
<div class="effectValue">{{operation}} {{signedEffectValue}}</div><div class="effectName"> {{name}}</div>
|
||||
{{#if editable}}
|
||||
<paper-icon-button id="editButton" icon="create" title="edit" role="button" aria-label="edit"></paper-icon-button>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
<template name="skillDialog">
|
||||
<!--needs character and skill string-->
|
||||
<paper-dialog layered="false" id="skillDialog" backdrop transition="core-transition-center">
|
||||
|
||||
</paper-dialog>
|
||||
<div class="scroll-y" fit>
|
||||
{{> abilityCards}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,151 +1,7 @@
|
||||
selectAttribute = function(name, title){
|
||||
Session.set("selectedAttribute", name);
|
||||
Session.set("selectedAttributeTitle", title);
|
||||
Session.set("editingEffect", null);
|
||||
};
|
||||
|
||||
selectSkill = function(name, title){
|
||||
Session.set("selectedSkill", name);
|
||||
Session.set("selectedSkillTitle", title);
|
||||
Session.set("editingEffect", null);
|
||||
};
|
||||
|
||||
Template.stats.created = function(){
|
||||
this.selectedSection = new ReactiveVar(0);
|
||||
}
|
||||
|
||||
Template.stats.events({
|
||||
"tap .attribute": function(event){
|
||||
var instance = Template.instance();
|
||||
var selected = $(event.currentTarget).attr("hero-id");
|
||||
var current = Session.get("selectedAttribute");
|
||||
var f = function(){
|
||||
selectAttribute(selected, "Title");
|
||||
instance.selectedSection.set(1);
|
||||
}
|
||||
//we already have the dialog open
|
||||
if(instance.selectedSection.get() === 1 && current != selected){
|
||||
instance.selectedSection.set(0);
|
||||
_.delay(f, 200);
|
||||
} else {
|
||||
f();
|
||||
}
|
||||
|
||||
},
|
||||
"tap #darkOverlay": function(event){
|
||||
Template.instance().selectedSection.set(0);
|
||||
// let the user click through before it is completely gone
|
||||
$("#darkOverlay").css("pointer-events", "none");
|
||||
// make clickable again later
|
||||
_.delay(function(){
|
||||
$("#darkOverlay").css("pointer-events", "auto");
|
||||
}, 500);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Template.stats.helpers({
|
||||
selectedSection: function(){
|
||||
return Template.instance().selectedSection.get();
|
||||
},
|
||||
isHero: function(string){
|
||||
if(string === Session.get("selectedAttribute")||
|
||||
string === Session.get("selectedSkill")){
|
||||
return "hero";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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");
|
||||
},
|
||||
attributeName: function(){
|
||||
return Session.get("selectedAttribute");
|
||||
},
|
||||
attribute: function(){
|
||||
return this.character.getField(Session.get("selectedAttribute"));
|
||||
},
|
||||
effects: function(){
|
||||
var attribute = this.character.getField(Session.get("selectedAttribute"));
|
||||
return _.groupBy(attribute.effects, "operation");
|
||||
},
|
||||
effectValue: function(){
|
||||
return evaluateEffect(Template.parentData(1).character._id, this);
|
||||
}
|
||||
});
|
||||
|
||||
Template.attributeEffect.helpers({
|
||||
editing: function(){
|
||||
return Session.get("editingEffect") === this._id;
|
||||
},
|
||||
editable: function(){
|
||||
return this.type === "editable";
|
||||
},
|
||||
operation: function(){
|
||||
switch(this.operation){
|
||||
case "add":
|
||||
return;
|
||||
case "mul":
|
||||
return Spacebars.SafeString("×");
|
||||
case "min":
|
||||
return "min";
|
||||
case "max":
|
||||
return "max";
|
||||
default:
|
||||
return this.operation;
|
||||
}
|
||||
},
|
||||
operationNumber: function(){
|
||||
switch(this.operation){
|
||||
case "add":
|
||||
return 0;
|
||||
case "mul":
|
||||
return 1;
|
||||
case "min":
|
||||
return 2;
|
||||
case "max":
|
||||
return 3;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
},
|
||||
signedEffectValue: function(){
|
||||
var value = evaluateEffect(Template.parentData(1).character._id, this);
|
||||
return signedString(value);
|
||||
}
|
||||
});
|
||||
|
||||
Template.attributeEffect.events({
|
||||
"tap #editButton": function(event){
|
||||
Session.set("editingEffect", this._id);
|
||||
},
|
||||
"tap #doneButton": function(event){
|
||||
var newEffect = {
|
||||
|
||||
};
|
||||
//TODO setup the changed effect
|
||||
var attribute = Session.get("selectedAttribute");
|
||||
var charId = Template.parentData(2)._id;
|
||||
Meteor.call("updateEffect", charId, attribute, this._id, newEffect)
|
||||
Session.set("editingEffect", null);
|
||||
},
|
||||
"tap #cancelButton": function(event){
|
||||
Session.set("editingEffect", null);
|
||||
},
|
||||
"tap #deleteButton": function(event){
|
||||
var attribute = Session.get("selectedAttribute");
|
||||
var pullObject = {};
|
||||
pullObject[attribute + ".effects"] = {_id: this._id};
|
||||
Characters.update(Template.parentData(2)._id, {$pull: pullObject});
|
||||
Session.set("editingEffect", null);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,6 +6,15 @@
|
||||
|
||||
<template name="featureDialog">
|
||||
{{#with feature}}
|
||||
<paper-menu-button>
|
||||
<paper-icon-button role="button" tabindex="0" icon="delete" aria-label="Delete Feature" noink></paper-icon-button>
|
||||
<paper-dropdown class="dropdown">
|
||||
<paper-button id="deleteFeature">Delete Feature</paper-button>
|
||||
<paper-button>Cancel</paper-button>
|
||||
</paper-dropdown>
|
||||
</paper-menu-button>
|
||||
|
||||
|
||||
<div class="featureDialogWidth"></div>
|
||||
<paper-input id="featureNameInput" label="Name" floatinglabel value={{name}}></paper-input>
|
||||
<paper-input-decorator label="Description" floatinglabel layout vertical>
|
||||
|
||||
@@ -4,20 +4,22 @@ Template.featureDialog.rendered = function(){
|
||||
var feature = Features.findOne(Template.currentData().featureId, {fields: {name: 1}});
|
||||
if(feature && feature.name) Session.set("global.ui.dialogHeader", feature.name);
|
||||
})
|
||||
//after the dialog is built, open it
|
||||
_.defer(function(){GlobalUI.dialog.open()});
|
||||
}
|
||||
|
||||
Template.featureDialog.events({
|
||||
"tap #deleteFeature": function(){
|
||||
Features.remove(this._id);
|
||||
GlobalUI.closeDialog()
|
||||
},
|
||||
"tap #addEffectButton": function(){
|
||||
var numUpdated = Features.update(this._id, {
|
||||
$push: {
|
||||
"effects": {
|
||||
name: "fe",
|
||||
operation: "add",
|
||||
type: "feature"
|
||||
}
|
||||
}
|
||||
Effects.insert({
|
||||
charId: Template.currentData().charId,
|
||||
sourceId: this._id,
|
||||
operation: "add",
|
||||
type: "feature"
|
||||
});
|
||||
console.log("pushed add button ", numUpdated, " updated");
|
||||
},
|
||||
"change #featureNameInput": function(event){
|
||||
var name = Template.instance().find("#featureNameInput").value;
|
||||
@@ -32,5 +34,9 @@ Template.featureDialog.events({
|
||||
Template.featureDialog.helpers({
|
||||
feature: function(){
|
||||
return Features.findOne(this.featureId);
|
||||
},
|
||||
effects: function(){
|
||||
var cursor = Effects.find({charId: Template.currentData().charId, type: "feature", sourceId: this._id})
|
||||
return cursor;
|
||||
}
|
||||
});
|
||||
@@ -1,43 +1,45 @@
|
||||
<template name="featureEffect">
|
||||
<paper-dropdown-menu id="statGroupDropDown" label="Stat Group">
|
||||
<paper-dropdown class="dropdown">
|
||||
<core-menu id="statGroupMenu" class="menu" selected={{selectedStatGroup}}>
|
||||
{{#each statGroups}}
|
||||
<paper-item>{{this}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{#if stats}}
|
||||
<paper-dropdown-menu id="statDropDown" label="Stat">
|
||||
<div class="featureEffect">
|
||||
<paper-dropdown-menu id="statGroupDropDown" label="Stat Group">
|
||||
<paper-dropdown class="dropdown">
|
||||
<core-menu id="statMenu" class="menu" selected={{selectedStat}}>
|
||||
{{#each stats}}
|
||||
<paper-item>{{name}}</paper-item>
|
||||
<core-menu id="statGroupMenu" class="menu" selected={{selectedStatGroup}}>
|
||||
{{#each statGroups}}
|
||||
<paper-item>{{this}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
{{#if operations}}
|
||||
<paper-dropdown-menu id="operationDropDown" label="Operation">
|
||||
<paper-dropdown class="dropdown">
|
||||
<core-menu id="operationMenu" class="menu" selected={{selectedOperation}}>
|
||||
{{#each operations}}
|
||||
<paper-item>{{name}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
{{> Template.dynamic template=effectValueTemplate data=valueTemplateData}}
|
||||
{{#if needsCommit}}
|
||||
<paper-icon-button id="commitChanges" role="button" tabindex="0" icon="check" aria-label="Commit Changes"></paper-icon-button>
|
||||
<paper-icon-button id="clearChanges" role="button" tabindex="0" icon="clear" aria-label="Clear Changes"></paper-icon-button>
|
||||
{{else}}
|
||||
<paper-icon-button id="deleteEffect" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
||||
{{/if}}
|
||||
<br>
|
||||
{{#if stats}}
|
||||
<paper-dropdown-menu id="statDropDown" label="Stat">
|
||||
<paper-dropdown class="dropdown">
|
||||
<core-menu id="statMenu" class="menu" selected={{selectedStat}}>
|
||||
{{#each stats}}
|
||||
<paper-item>{{name}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
{{#if operations}}
|
||||
<paper-dropdown-menu id="operationDropDown" label="Operation">
|
||||
<paper-dropdown class="dropdown">
|
||||
<core-menu id="operationMenu" class="menu" selected={{selectedOperation}}>
|
||||
{{#each operations}}
|
||||
<paper-item>{{name}}</paper-item>
|
||||
{{/each}}
|
||||
</core-menu>
|
||||
</paper-dropdown>
|
||||
</paper-dropdown-menu>
|
||||
{{/if}}
|
||||
{{> Template.dynamic template=effectValueTemplate data=valueTemplateData}}
|
||||
{{#if needsCommit}}
|
||||
<paper-icon-button id="commitChanges" role="button" tabindex="0" icon="check" aria-label="Commit Changes"></paper-icon-button>
|
||||
<paper-icon-button id="clearChanges" role="button" tabindex="0" icon="clear" aria-label="Clear Changes"></paper-icon-button>
|
||||
{{else}}
|
||||
<paper-icon-button id="deleteEffect" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
|
||||
{{/if}}
|
||||
<br>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="regularEffectValue">
|
||||
|
||||
@@ -233,19 +233,19 @@ Template.featureEffect.helpers({
|
||||
|
||||
Template.featureEffect.events({
|
||||
"tap #commitChanges": function(event){
|
||||
var newEffect = this;
|
||||
var changedFields = {};
|
||||
var inst = Template.instance();
|
||||
newEffect.operation = inst.selectedOperation.get();
|
||||
newEffect.stat = inst.selectedStat.get();
|
||||
changedFields.operation = inst.selectedOperation.get();
|
||||
changedFields.stat = inst.selectedStat.get();
|
||||
var val = inst.value.get();
|
||||
if(_.isNumber(val)){
|
||||
newEffect.value = val;
|
||||
newEffect.calculation = null;
|
||||
changedFields.value = val;
|
||||
changedFields.calculation = null;
|
||||
} else if(_.isString(val)) {
|
||||
newEffect.calculation = val;
|
||||
newEffect.value = null;
|
||||
changedFields.calculation = val;
|
||||
changedFields.value = null;
|
||||
}
|
||||
Meteor.call("updateFeatureEffect", Template.parentData()._id, newEffect);
|
||||
Effects.update(this._id, {$set: changedFields});
|
||||
},
|
||||
"tap #clearChanges": function(event){
|
||||
//essentially re-render
|
||||
@@ -262,10 +262,12 @@ Template.featureEffect.events({
|
||||
inst.value.set(value);
|
||||
},
|
||||
"tap #deleteEffect": function(event){
|
||||
Features.update(Template.parentData()._id, { $pull: { "effects": {_id: this._id} } });
|
||||
Effects.remove(this._id);
|
||||
},
|
||||
"core-select #statGroupMenu": function(event){
|
||||
var groupIndex = Template.instance().find("#statGroupMenu").selected;
|
||||
var groupMenu = Template.instance().find("#statGroupMenu")
|
||||
if(!groupMenu) return;
|
||||
var groupIndex = groupMenu.selected;
|
||||
var groupName = statGroupNames[groupIndex]
|
||||
var oldName = Template.instance().selectedStatGroup.get();
|
||||
if(oldName != groupName){
|
||||
@@ -277,8 +279,11 @@ Template.featureEffect.events({
|
||||
}
|
||||
},
|
||||
"core-select #statMenu": function(event){
|
||||
var statIndex = Template.instance().find("#statMenu").selected;
|
||||
var groupIndex = Template.instance().find("#statGroupMenu").selected;
|
||||
var statMenu = Template.instance().find("#statMenu");
|
||||
var groupMenu = Template.instance().find("#statGroupMenu");
|
||||
if(!statMenu || !groupMenu) return;
|
||||
var statIndex = statMenu.selected;
|
||||
var groupIndex = groupMenu.selected;
|
||||
var groupName = statGroupNames[groupIndex]
|
||||
var group = statGroups[groupName];
|
||||
var statObj = group[statIndex];
|
||||
@@ -289,7 +294,9 @@ Template.featureEffect.events({
|
||||
"core-select #operationMenu": function(event){
|
||||
var groupName = Template.instance().selectedStatGroup.get();
|
||||
var opGroup = (groupName === "Saving Throws" || groupName === "Skills")? skillOperations : attributeOperations;
|
||||
var opIndex = Template.instance().find("#operationMenu").selected;
|
||||
var opMenu = Template.instance().find("#operationMenu")
|
||||
if(!opMenu) return;
|
||||
var opIndex = opMenu.selected;
|
||||
var op = opGroup[opIndex];
|
||||
if(!op) return;
|
||||
var opName = op.operation;
|
||||
@@ -297,7 +304,9 @@ Template.featureEffect.events({
|
||||
},
|
||||
"core-select #multiplierMenu": function(event){
|
||||
var inst = Template.instance();
|
||||
var selected = Template.instance().find("#multiplierMenu").selected;
|
||||
var mulMenu = Template.instance().find("#multiplierMenu");
|
||||
if(!mulMenu) return;
|
||||
var selected = mulMenu.selected;
|
||||
if(selected === 0){
|
||||
inst.value.set(0.5);
|
||||
inst.selectedOperation.set("mul");
|
||||
@@ -311,7 +320,9 @@ Template.featureEffect.events({
|
||||
},
|
||||
"core-select #proficiencyMenu": function(event){
|
||||
var inst = Template.instance();
|
||||
var selected = inst.find("#proficiencyMenu").selected;
|
||||
var profMenu = inst.find("#proficiencyMenu");
|
||||
if(!profMenu) return;
|
||||
var selected = profMenu.selected;
|
||||
var value;
|
||||
if(selected === 0){
|
||||
inst.value.set(1);
|
||||
@@ -323,7 +334,9 @@ Template.featureEffect.events({
|
||||
},
|
||||
"change #effectValueInput": function(event){
|
||||
var inst = Template.instance();
|
||||
var value = inst.find("#effectValueInput").value;
|
||||
var input = inst.find("#effectValueInput");
|
||||
if(!input) return;
|
||||
var value = input.value;
|
||||
inst.value.set(value);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
paper-shadow.featureCard {
|
||||
width: 300px;
|
||||
padding: 16px;
|
||||
margin: 8px;
|
||||
margin: 4px;
|
||||
background: white;
|
||||
}
|
||||
flex-grow: 1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.features {
|
||||
display: flex !important;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
flex-wrap: wrap;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.featureCardTop {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.featureCardBottom {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
#addFeature {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
#addFeature {
|
||||
bottom: 16px;
|
||||
right: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
<template name="features">
|
||||
<div class="resources"><!--resources-->
|
||||
|
||||
<div fit>
|
||||
<div class="scroll-y" fit>
|
||||
<div class="resources"><!--resources-->
|
||||
|
||||
</div>
|
||||
<div class="actions">
|
||||
|
||||
</div>
|
||||
<div class="features">
|
||||
{{#each features}}
|
||||
<paper-shadow class="featureCard">
|
||||
<div class="featureCardTop">
|
||||
<h2>{{name}}</h2>
|
||||
</div>
|
||||
<div class="featureCardBottom"><p>{{description}}</p></div>
|
||||
<paper-ripple fit></paper-ripple>
|
||||
</paper-shadow>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="fab-buffer"></div>
|
||||
</div>
|
||||
<paper-fab id="addFeature" icon="add" title="Add" role="button" tabindex="0" aria-label="Add"></paper-fab>
|
||||
</div>
|
||||
<div class="actions">
|
||||
|
||||
</div>
|
||||
<div class="features">
|
||||
{{#each features}}
|
||||
<paper-shadow class="featureCard">
|
||||
<div class="featureCardTop">
|
||||
<h1>{{name}}</h1>
|
||||
</div>
|
||||
<div class="featureCardBottom">
|
||||
<p>{{description}}</p>
|
||||
</div>
|
||||
<paper-ripple fit></paper-ripple>
|
||||
</paper-shadow>
|
||||
{{/each}}
|
||||
</div>
|
||||
<paper-fab id="addFeature" icon="add" title="Add" role="button" tabindex="0" aria-label="Add"></paper-fab>
|
||||
</template>
|
||||
@@ -11,16 +11,16 @@ Template.features.events({
|
||||
GlobalUI.showDialog({
|
||||
heading: "New Feature",
|
||||
template: "featureDialog",
|
||||
data: {featureId: featureId},
|
||||
data: {featureId: featureId, charId: this._id},
|
||||
fullOnMobile: true
|
||||
})
|
||||
},
|
||||
"tap .featureCard": function(event){
|
||||
var featureId = this._id;
|
||||
GlobalUI.showDialog({
|
||||
GlobalUI.setDialog({
|
||||
heading: this.name,
|
||||
template: "featureDialog",
|
||||
data: {featureId: featureId},
|
||||
data: {featureId: featureId, charId: Template.parentData()._id},
|
||||
fullOnMobile: true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
body /deep/ .featureDialogWidth {
|
||||
width: 600px;
|
||||
width: 560px;
|
||||
}
|
||||
|
||||
body /deep/ #statGroupDropDown {
|
||||
@@ -20,4 +20,13 @@ body /deep/ #damageMultiplierDropDown {
|
||||
|
||||
body /deep/ #proficiencyDropDown {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
html /deep/ paper-input {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
html /deep/ .featureEffect {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
@@ -6,10 +6,13 @@
|
||||
<link rel="import" href="/components/core-item/core-item.html">
|
||||
<link rel="import" href="/components/core-menu/core-menu.html">
|
||||
<link rel="import" href="/components/core-scaffold/core-scaffold.html">
|
||||
<link rel="import" href="/components/core-transition/core-transition.html">
|
||||
|
||||
<!--paper components-->
|
||||
<link rel="import" href="/components/paper-button/paper-button.html">
|
||||
<link rel="import" href="/components/paper-dialog/paper-action-dialog.html">
|
||||
<link rel="import" href="/components/paper-dialog/paper-dialog.html">
|
||||
<link rel="import" href="/components/paper-dialog/paper-dialog-transition.html">
|
||||
<link rel="import" href="/components/paper-dropdown/paper-dropdown.html">
|
||||
<link rel="import" href="/components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||
<link rel="import" href="/components/paper-fab/paper-fab.html">
|
||||
@@ -18,6 +21,7 @@
|
||||
<link rel="import" href="/components/paper-input/paper-input.html">
|
||||
<link rel="import" href="/components/paper-input/paper-input-decorator.html">
|
||||
<link rel="import" href="/components/paper-item/paper-item.html">
|
||||
<link rel="import" href="/components/paper-menu-button/paper-menu-button.html">
|
||||
<link rel="import" href="/components/paper-shadow/paper-shadow.html">
|
||||
<link rel="import" href="/components/paper-spinner/paper-spinner.html">
|
||||
<link rel="import" href="/components/paper-tabs/paper-tabs.html">
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
</core-drawer-panel>
|
||||
|
||||
<paper-action-dialog global-dialog backdrop
|
||||
transition="paper-dialog-transition-bottom"
|
||||
class={{#if globalDialogFullOnMobile}}full-on-mobile{{/if}}
|
||||
transition="core-transition-center"
|
||||
class="scrolling {{#if globalDialogFullOnMobile}}full-on-mobile{{/if}}"
|
||||
autoclosedisabled
|
||||
heading={{globalDialogHeader}}
|
||||
layered>
|
||||
|
||||
@@ -3,5 +3,5 @@ getMod = function(score){
|
||||
}
|
||||
|
||||
signedString = function(number){
|
||||
return number > 0? "+" + number : "" + number;
|
||||
return number >= 0? "+" + number : "" + number;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
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});
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
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});
|
||||
};
|
||||
@@ -1,41 +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 }
|
||||
)
|
||||
},
|
||||
updateFeatureEffect: function (featureId, newEffect) {
|
||||
var selector = {_id: featureId};
|
||||
selector["effects._id"] = newEffect._id;
|
||||
var setter = {};
|
||||
setter["effects.$"] = newEffect
|
||||
Features.update(
|
||||
selector,
|
||||
{ $set: setter }
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
//pull a single effect by stat and id
|
||||
pullEffect = function(id, effect){
|
||||
if(effect.stat){
|
||||
var pullObject = {};
|
||||
pullObject[effect.stat + ".effects"] = {_id: effect._id};
|
||||
Characters.update(id, {$pull: pullObject });
|
||||
}
|
||||
},
|
||||
|
||||
pushEffect = function(id, effect){
|
||||
if(effect.stat){
|
||||
var pushObject = {};
|
||||
pushObject[effect.stat + ".effects"] = effect;
|
||||
Characters.update(id, {$push: pushObject});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
addFeatureEffects = function(charId, newFeature){
|
||||
_.each(newFeature.effects, function(effect){
|
||||
if(newFeature.name) effect.name = newFeature.name;
|
||||
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(oldFeature.attacks, function(attack){
|
||||
pullAttack(charId, attack);
|
||||
});
|
||||
_.each(oldFeature.spells, function(spell){
|
||||
pullSpell(charId, spell);
|
||||
});
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
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});
|
||||
};
|
||||
8
rpg-docs/nohup.out
Normal file
8
rpg-docs/nohup.out
Normal file
@@ -0,0 +1,8 @@
|
||||
[[[[[ ~/workspace/rpg-docs ]]]]]
|
||||
|
||||
=> Started proxy.
|
||||
=> Started MongoDB.
|
||||
Vulcanize: Adding all imports...
|
||||
=> Started your app.
|
||||
|
||||
=> App running at: http://localhost:3000/
|
||||
@@ -13,4 +13,8 @@ Meteor.publish("characterItems", function(characterId, userId){
|
||||
|
||||
Meteor.publish("characterFeatures", function(characterId, userId){
|
||||
return Features.find({charId: characterId});
|
||||
});
|
||||
});
|
||||
|
||||
Meteor.publish("characterEffects", function(characterId, userId){
|
||||
return Effects.find({charId: characterId});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user