commit 2a82e39cf0a913224715567695e42bdd08ef5fc2 Author: Thaum Date: Mon Nov 3 06:17:35 2014 +0000 init diff --git a/.codio b/.codio new file mode 100644 index 00000000..7d7bce0e --- /dev/null +++ b/.codio @@ -0,0 +1,16 @@ +{ +// Configure your Run and Preview buttons here. + +// Run button configuration + "commands": { + "Node version": "node --version" + }, + +// Preview button configuration + "preview": { + "Project Index (static)": "https://{{domain}}/{{index}}", + "Current File (static)": "https://{{domain}}/{{filepath}}", + "Box URL": "http://{{domain}}:3000/", + "Box URL SSL": "https://{{domain}}:9500/" + } +} \ No newline at end of file diff --git a/.guides/sections.md b/.guides/sections.md new file mode 100644 index 00000000..43c39cb8 --- /dev/null +++ b/.guides/sections.md @@ -0,0 +1,26 @@ +--- +title: Example section +files: [] +editable: true +layout: 2-panels-tree + +--- +Some **awesome** content 1 + +--- +title: Example section 3 +files: [] +editable: true +layout: "" + +--- +Some **awesome** content 3 + +--- +title: Example section 4 +files: [] +editable: true +layout: "" + +--- +Some **awesome** content 4 diff --git a/.guides/styles.css b/.guides/styles.css new file mode 100644 index 00000000..bde588d3 --- /dev/null +++ b/.guides/styles.css @@ -0,0 +1 @@ +/* Place you styles here */ \ No newline at end of file diff --git a/TODO.md b/TODO.md new file mode 100644 index 00000000..e6f6f862 --- /dev/null +++ b/TODO.md @@ -0,0 +1,37 @@ +Character.js is under construction... expect broken character sheets + +issues +------ + +* hot code pushes don't apply transforms correctly + +Characters attributes and buffs +------------------------------- + +Characters currently have attributes and skills that can take bonuses and multipliers. +When a feature is activated or enabled on a characer or a piece of equipment is equipped +the buffs and effects should be applied to the correct attribute or skill. When the +equipment or feature is removed or deactivated, the effects should be removed as well. + +Effects need the following data as a bare minimum: + +* attribute or skill to effect +* name +* value + +For example, plate would be an object like this: + + { + name: "Plate Armor" , + effects: [ + {stat: "skills.dexArmor.min", value: 0}, + {stat: "skills.dexArmor.max", value: 0}, + {stat: "attributes.armor.min", value: 18}, + {stat: "skills.stealth.disadvantage", value 1} //disadvantage doesn't need a value + ] + } + +See Conditions for this implemented. + +The effects ultimately need to be pushed to the correct array when applied: `attributes.armor.min.push({name: "Plate Armor", type: "Equpiment", value: 18})` +They will also need to be removed correctly by the thing that applied them, or after some time. \ No newline at end of file diff --git a/rpg-docs/.meteor/.finished-upgraders b/rpg-docs/.meteor/.finished-upgraders new file mode 100644 index 00000000..ee0ed5a3 --- /dev/null +++ b/rpg-docs/.meteor/.finished-upgraders @@ -0,0 +1,6 @@ +# This file contains information which helps Meteor properly upgrade your +# app when you run 'meteor update'. You should check it into version control +# with your project. + +notices-for-0.9.0 +notices-for-0.9.1 diff --git a/rpg-docs/.meteor/.gitignore b/rpg-docs/.meteor/.gitignore new file mode 100644 index 00000000..40830374 --- /dev/null +++ b/rpg-docs/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/rpg-docs/.meteor/.id b/rpg-docs/.meteor/.id new file mode 100644 index 00000000..7d3b47c6 --- /dev/null +++ b/rpg-docs/.meteor/.id @@ -0,0 +1,7 @@ +# This file contains a token that is unique to your project. +# Check it into your repository along with the rest of this directory. +# It can be used for purposes such as: +# - ensuring you don't accidentally deploy one app on top of another +# - providing package authors with aggregated statistics + +1xg0ir21aq4e081rfkzg3 diff --git a/rpg-docs/.meteor/cordova-plugins b/rpg-docs/.meteor/cordova-plugins new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/rpg-docs/.meteor/cordova-plugins @@ -0,0 +1 @@ + diff --git a/rpg-docs/.meteor/packages b/rpg-docs/.meteor/packages new file mode 100644 index 00000000..1007889f --- /dev/null +++ b/rpg-docs/.meteor/packages @@ -0,0 +1,13 @@ +# Meteor packages used by this project, one per line. +# +# 'meteor add' and 'meteor remove' will edit this file for you, +# but you can also edit it by hand. + +meteor-platform +autopublish +insecure +iron:router +accounts-password +accounts-ui +random + diff --git a/rpg-docs/.meteor/release b/rpg-docs/.meteor/release new file mode 100644 index 00000000..55ab0eca --- /dev/null +++ b/rpg-docs/.meteor/release @@ -0,0 +1 @@ +METEOR@0.9.2.2 diff --git a/rpg-docs/.meteor/versions b/rpg-docs/.meteor/versions new file mode 100644 index 00000000..966f4117 --- /dev/null +++ b/rpg-docs/.meteor/versions @@ -0,0 +1,66 @@ +accounts-base@1.1.0 +accounts-password@1.0.1 +accounts-ui-unstyled@1.1.1 +accounts-ui@1.1.0 +application-configuration@1.0.2 +autopublish@1.0.0 +autoupdate@1.1.0 +base64@1.0.0 +binary-heap@1.0.0 +blaze-tools@1.0.0 +blaze@2.0.0 +boilerplate-generator@1.0.0 +callback-hook@1.0.0 +check@1.0.0 +ctl-helper@1.0.3 +ctl@1.0.1 +ddp@1.0.8 +deps@1.0.3 +ejson@1.0.2 +email@1.0.2 +fastclick@1.0.0 +follower-livedata@1.0.1 +geojson-utils@1.0.0 +html-tools@1.0.0 +htmljs@1.0.1 +http@1.0.5 +id-map@1.0.0 +insecure@1.0.0 +iron:core@0.3.4 +iron:dynamic-template@0.4.1 +iron:layout@0.4.1 +iron:router@0.9.4 +jquery@1.0.0 +json@1.0.0 +less@1.0.8 +livedata@1.0.9 +localstorage@1.0.0 +logging@1.0.3 +meteor-platform@1.1.0 +meteor@1.1.0 +minifiers@1.1.0 +minimongo@1.0.3 +mobile-status-bar@1.0.0 +mongo@1.0.5 +npm-bcrypt@0.7.7 +observe-sequence@1.0.2 +ordered-dict@1.0.0 +random@1.0.0 +reactive-dict@1.0.2 +reactive-var@1.0.1 +reload@1.1.0 +retry@1.0.0 +routepolicy@1.0.1 +service-configuration@1.0.1 +session@1.0.1 +sha@1.0.0 +spacebars-compiler@1.0.2 +spacebars@1.0.1 +srp@1.0.0 +templating@1.0.6 +tracker@1.0.2 +ui@1.0.2 +underscore@1.0.0 +url@1.0.0 +webapp-hashing@1.0.0 +webapp@1.1.1 diff --git a/rpg-docs/Model/Character/Armor.js b/rpg-docs/Model/Character/Armor.js new file mode 100644 index 00000000..d81b1a98 --- /dev/null +++ b/rpg-docs/Model/Character/Armor.js @@ -0,0 +1,9 @@ +Armor = function(name, value){ + this.name = name; + this.value = value; + this.equipped = true; + this.dexModMax = 20; + this.dexModMin = -20; + this.strengthNeeded = 0; + this.stealthDisadvantage = false; +} \ No newline at end of file diff --git a/rpg-docs/Model/Character/Characters.js b/rpg-docs/Model/Character/Characters.js new file mode 100644 index 00000000..84f91341 --- /dev/null +++ b/rpg-docs/Model/Character/Characters.js @@ -0,0 +1,324 @@ +//set up the collection for characters +Characters = new Meteor.Collection("characters", { + //transform function alters the object returned by the database + transform: function (doc) { + //extend character with its protoypal functions + var newInstance = Object.create(protoCharacter); + doc = _.extend(newInstance, doc); + + return doc; + } +}); + +//Attributes are numerical values +Attribute = function(base){ + this.base = base; //the unmodified value of the attribute + //effects of the form {name: "Ring of Protection", value: 1} + this.add = []; //bonuses added to the attribute + this.mul = []; //multipliers to the attribute (after adding bonuses) + this.min = []; //effects setting the minimum value of the attribute + this.max = []; //effects setting the maximum value of the attribute + this.conditional = []; //conditional modifiers +} + +var attributes = [ + "strength", + "dexterity", + "constitution", + "intelligence", + "wisdom", + "charisma", + "hitPoints", + "proficiencyBonus", + "speed", + "armor", + "weight", + "weightCarried", + "age", + "ageRate", + "level1SpellSlots", + "level2SpellSlots", + "level3SpellSlots", + "level4SpellSlots", + "level5SpellSlots", + "level6SpellSlots", + "level7SpellSlots", + "level8SpellSlots", + "level9SpellSlots", + "ki", + "sorceryPoints", + "rages" +]; + +//Skills are bonuses to rolls: "+2" etc. +//They are based off of some ability +Skill = function(ability){ + //proficiencies of the form {name: "Jack of all Trades", value: 0.5} + //only the highest is used + this.proficiency = []; + //ability name that this skill uses as base for roll + this.ability = ability; + this.add = []; + this.mul = []; + this.min = []; + this.max = []; + this.advantage = []; //effects granting advantage + this.disadvantage = []; + this.passiveAdd = []; //only added to passive checks + this.fail = []; //all checks are failed + this.conditional = []; //conditional modifiers +} + +var skills = [ + {skill: "strengthSave", ability: "strength"}, + {skill: "dexteritySave", ability: "dexterity"}, + {skill: "constitutionSave", ability: "constitution"}, + {skill: "intelligenceSave", ability: "intelligence"}, + {skill: "wisdomSave", ability: "wisdom"}, + {skill: "charismaSave", ability: "charisma"}, + + {skill: "acrobatics", ability: "dexterity"}, + {skill: "animalHandling", ability: "wisdom"}, + {skill: "arcana",ability: "intelligence"}, + {skill: "athletics", ability: "strength"}, + {skill: "deception", ability: "charisma"}, + {skill: "history", ability: "intelligence"}, + {skill: "insight", ability: "wisdom"}, + {skill: "intimidation", ability: "charisma"}, + {skill: "investigation", ability: "intelligence"}, + {skill: "medicine", ability: "wisdom"}, + {skill: "nature", ability: "intelligence"}, + {skill: "perception", ability: "wisdom"}, + {skill: "performance", ability: "charisma"}, + {skill: "persuasion", ability: "charisma"}, + {skill: "religion", ability: "intelligence"}, + {skill: "sleightOfHand", ability: "dexterity"}, + {skill: "stealth", ability: "dexterity"}, + {skill: "survival", ability: "wisdom"}, + + {skill: "initiative", ability: "dexterity"}, + {skill: "strengthAttack", ability: "strength"}, + {skill: "dexterityAttack", ability: "dexterity"}, + {skill: "rangedAttack", ability: "dexterity"}, + {skill: "dexterityArmor", ability: "dexterity"} + +]; + +//Plain text fields for the character +var strings = [ + "name", + "alignment", + "gender", + "race", + "description", + "personality", + "ideals", + "bonds", + "flaws" +]; + +//Data structure for the character +//no functions can be added to this constructor +Character = function(owner){ + //attributes + this.attributes = {}; + for(var i = 0, l = attributes.length; i < l; i++){ + this.attributes[attributes[i]] = new Attribute(0); + } + + //add 10 and dex bonus to armor + this.attributes.armor.add.push({name: "Base Armor Class", value: 10}); + this.attributes.armor.add.push({name: "Dexterity Modifier", value: "skillMod skills.dexterityArmor"}); + + //skills + this.skills = {}; + for(var i = 0, l = skills.length; i < l; i++){ + this.skills[skills[i].skill] = new Skill(skills[i].ability); + } + + this.deathSave = { + success : 0, + fail: 0 + }; + + this.hitDice = []; + + this.weaponProficiencies = []; + this.toolProficiencies = []; + this.languages = []; + + this.features = []; + + this.spells = []; + + this.classes = []; + + this.experience = new Experience(); + + this.vulnerability = {}; + for(var i = 0, l = DamageTypes.length; i < l; i++){ + this.vulnerability[DamageTypes[i]] = new Attribute(1); + this.vulnerability[DamageTypes[i]].min.push({name: "Resistance doesn't stack", value: 0.5}); + this.vulnerability[DamageTypes[i]].max.push({name: "Vulnerability doesn't stack", value: 2}); + } + + //admin + this.owner = owner; + this.readers = []; + this.writers = []; +} + +//functions and calculated values go here +var protoCharacter = { + attributeValue: function(attribute){ + if (attribute === undefined) return; + //base value + var value = attribute.base; + + //add all values in add array + for(var i = 0, l = attribute.add.length; i < l; i++){ + var add = pop(attribute.add[i].value, this); + value += add ; + } + + //multiply all values in mul array + for(var i = 0, l = attribute.mul.length; i < l; i++){ + var mul = pop(attribute.mul[i], this); + value *= mul; + } + + //largest min + for(var i = 0, l = attribute.min.length; i < l; i++){ + var min = pop(attribute.min[i], this); + value = value > min? value : min; + } + + //smallest max + for(var i = 0, l = attribute.max.length; i < l; i++){ + var max = pop(attribute.max[i], this); + value = value < max? value : max; + } + + return value; + }, + + skillMod: function(skill){ + //get the final value of the ability score + var ability = this.attributeValue(this.attributes[skill.ability]); + + //base modifier + var mod = +getMod(ability) + + //multiply proficiency bonus by largest value in proficiency array + var prof = 0; + for(var i = 0, l = skill.proficiency.length; i < l; i++){ + var newProf = pop(skill.proficiency[i].value, this); + if (newProf > prof){ + prof = newProf; + } + } + //add multiplied proficiency bonus to modifier + mod += prof * this.attributeValue(this.attributes.proficiencyBonus); + + //add all values in add array + for(var i = 0, l = skill.add.length; i < l; i++){ + mod += pop(skill.add[i].value, this); + } + + //multiply all values in mul array + for(var i = 0, l = skill.mul.length; i < l; i++){ + mod *= pop(skill.mul[i].value, this); + } + + //largest min + for(var i = 0, l = skill.min.length; i < l; i++){ + var min = pop(skill.min[i], this); + mod = mod > min? mod : min; + } + + //smallest max + for(var i = 0, l = skill.max.length; i < l; i++){ + var max = pop(skill.max[i], this); + mod = mod < max? mod : max; + } + + return signedString(mod); + }, + + passiveSkill: function(skill){ + var mod = +this.skillMod(skill); + var value = 10 + mod; + for(var i = 0, l = skill.passiveAdd.length; i < l; i++){ + value += pop(skill.passiveAdd[i].value, this); + } + return value; + //TODO decide whether (dis)advantage gives (-)+5 to passive checks + }, + + abilityMod: function(attribute){ + return signedString(getMod(this.attributeValue(attribute))); + }, + + passiveAbility: function(attribute){ + var mod = +getMod(this.attributeValue(attribute)); + return 10 + mod; + } +} + +getMod = function(score){ + return Math.floor((score-10)/2); +} + +signedString = function(number){ + return number > 0? "+" + number : "" + number; +} + +// turns dot notation strings into keys of root +// argument formats: + // 157, anything -> 157 + // "some.number", object -> object.some.number + // "some.function", object -> object.some.function() + // "some.function arg1 arg2", object -> object.some.function(arg1, arg2) +pop = function(input, root){ + + if(typeof(input) === "string"){ + //we need root for this part + if(root === undefined) return; + + //this is a likely to fail if the string is malformed + try{ + //split over spaces + var parts = input.split(" "); + + //for each word + for (var i = 0; i < parts.length; i++){ + //split over dots + var str = parts[i].split("."); + + //start at root + parts[i] = root; + + //for each word between dots + for (var j = 0; j < str.length; j++){ + parts[i] = parts[i][str[j]]; + } + } + + //pull the first word out, might be a function + var func = parts.splice(0, 1)[0]; + + //if it's a function, apply the arguments to it + if(_.isFunction(func)) return +func.apply(root, parts); + + //if it's a number, return it + if(!isNaN(func)) return +func; + } catch (err) { + //TODO pokemon catch statement is bad + //"gotta catch em all" + console.log(err); + return; + } + } + + return +input; +} \ No newline at end of file diff --git a/rpg-docs/Model/Character/Conditions.js b/rpg-docs/Model/Character/Conditions.js new file mode 100644 index 00000000..322a96f6 --- /dev/null +++ b/rpg-docs/Model/Character/Conditions.js @@ -0,0 +1,118 @@ +DamageTypes = [ + "acid", "bludgeoning", "cold", "fire", "force", + "lightning", "necrotic", "piercing", "poison", "psychic", + "radiant", "slashing", "thunder" +] +Conditions = {}; + +Conditions.Blinded = { + description: ["a blinded creature can't see and automatically fails any ability check that requires sight.", + "Attack rolls against the creature have advantage, and the creature's attack rolls have disadvantage."] +} + +Conditions.Charmed = { + description: ["A charmed creature can't attack the charmer or target the charmer with harmful abilities or magical effects", + "The charmer has advantage on any ability check to interact socially with the creature."] +} + +Conditions.Deafened = { + description: ["A deafened creature can't hear and automatically fails any ability check that requires hearing"] +} + +Conditions.Frightened = { + description: [] +} + +Conditions.Grappled = { + description: [ + "A grappled creature's speed becomes 0, and it can't benefit from any bonuses to its speed", + "The condition ends if the grappler is incapacitated", + "The conditions also ends if if an effect removes the\ +grappled creature from the reach of the grappler or grappling\ +effect, such as when a creature is hurled\ +away by the thunderwave spell." + ], + effects: [ + {stat: "attributes.speed.maximum", value: 0} + ] +} + +Conditions.Incapacitated = { + effects: [ + {stat: "attributes.actions.maximum", value: 0}, + {stat: "attributes.reactions.maximum", value: 0}, + {stat: "attributes.bonusActions.maximum", value: 0} + ] +} + +Conditions.Invisible = { + +} + +Conditions.Paralyzed = { + //implies incapacitated + effects: [ + {stat: "skills.strengthSave.fail", value: 1}, + {stat: "skills.dexteritySave.fail", value: 1}, + {stat: "attributes.speed.maximum", value: 0} + ] +} +_.extend(Conditions.Paralyzed, Conditions.Incapacitated); + +Conditions.Petrified = { + + effects: [ + {stat: "attributes.weight.mul", value: 10}, + {stat: "attributes.ageRate.max", value: 0}, + {stat: "attributes.ageRate.min", value: 0}, + {stat: "skills.strengthSave.fail", value: 1}, + {stat: "skills.dexteritySave.fail", value: 1}, + {stat: "attributes.speed.maximum", value: 0} + ] +} +for(var i = 0, l = DamageTypes.length; i < l; i++){ + var str = "vulnerability." + DamageTypes[i] + ".mul" + Conditions.Petrified.effects.push({stat: str, value: 0.5}); +} +_.extend(Conditions.Petrified, Conditions.Incapacitated); + +Conditions.Poisoned = { + description: [] +} + +Conditions.Prone = { + description: [], + effects: [ + {stat: "skills.strengthAttack.disadvantage", value: 1}, + {stat: "skills.dexterityAttack.disadvantage", value: 1}, + {stat: "skills.rangedAttack.disadvantage", value: 1} + ] +} + +Conditions.Restrained = { + effects: [ + {stat: "attributes.speed.maximum", value: 0} + ] +} + +Conditions.Stunned = { + //implies incapacitated + effects: [ + {stat: "attributes.speed.maximum", value: 0}, + {stat: "skills.strengthSave.fail", value: 1}, + {stat: "skills.dexteritySave.fail", value: 1} + ] +} +_.extend(Conditions.Stunned, Conditions.Incapacitated); + +Conditions.Unconscious = { + //implies incapacitated + //implies prone + effects: [ + {stat: "attributes.speed.maximum", value: 0}, + {stat: "skills.strengthSave.fail", value: 1}, + {stat: "skills.dexteritySave.fail", value: 1} + ] +} +_.extend(Conditions.Unconscious, Conditions.Incapacitated); +_.extend(Conditions.Unconscious, Conditions.Prone); \ No newline at end of file diff --git a/rpg-docs/Model/Character/Experience.js b/rpg-docs/Model/Character/Experience.js new file mode 100644 index 00000000..6a5a80b3 --- /dev/null +++ b/rpg-docs/Model/Character/Experience.js @@ -0,0 +1,52 @@ +Experience = function(){ + this.total = 0; + this.events = []; + this.level = 0; +} + +Experience.prototype.addEvent = function(description, value){ + this.events.push({ + "description": description, + "value": value + }) + this.total += value; + this.level = this.getLevel(); +} + +Experience.prototype.removeEvent = function(index){ + this.total -= this.events[index].value; + this.events.splice(index,1); + this.level = this.getLevel(); +} + +Experience.prototype.refreshTotal = function(){ + this.total = 0; + for(var i = 0, length = this.events.length; i < length; i++){ + this.total += this.events[i].value; + } + this.level = this.getLevel(); +} + +Experience.prototype.getLevel = function(){ + var xp = this.total; + if(xp > 355000) return 20; + if(xp > 305000) return 19; + if(xp > 265000) return 18; + if(xp > 225000) return 17; + if(xp > 195000) return 16; + if(xp > 165000) return 15; + if(xp > 140000) return 14; + if(xp > 120000) return 13; + if(xp > 100000) return 12; + if(xp > 85000) return 11; + if(xp > 64000) return 10; + if(xp > 48000) return 9; + if(xp > 34000) return 8; + if(xp > 23000) return 7; + if(xp > 14000) return 6; + if(xp > 6500) return 5; + if(xp > 2700) return 4; + if(xp > 900) return 3; + if(xp > 300) return 2; + return 1; +} \ No newline at end of file diff --git a/rpg-docs/Model/Character/Feature.js b/rpg-docs/Model/Character/Feature.js new file mode 100644 index 00000000..942473ab --- /dev/null +++ b/rpg-docs/Model/Character/Feature.js @@ -0,0 +1,4 @@ +Feature = function(name){ + this.name = name; + this.description = description; +} \ No newline at end of file diff --git a/rpg-docs/Model/Character/HitDice.js b/rpg-docs/Model/Character/HitDice.js new file mode 100644 index 00000000..4731a1c6 --- /dev/null +++ b/rpg-docs/Model/Character/HitDice.js @@ -0,0 +1,6 @@ +HitDice = function(sides){ + this.sides = sides; + this.bonus = 0; + this.number = 0; + this.max = 0; +} \ No newline at end of file diff --git a/rpg-docs/Model/Character/Spell.js b/rpg-docs/Model/Character/Spell.js new file mode 100644 index 00000000..4a15ebe2 --- /dev/null +++ b/rpg-docs/Model/Character/Spell.js @@ -0,0 +1,11 @@ +Spell = function(name){ + this.name = name; + this.level = 0; + this.school = ""; + this.range = ""; + this.verbal = false; + this.somatic = false; + this.material = false; + this.duration = ""; + this.description = ""; +} \ No newline at end of file diff --git a/rpg-docs/Model/Inventory/Containers.js b/rpg-docs/Model/Inventory/Containers.js new file mode 100644 index 00000000..11a66f34 --- /dev/null +++ b/rpg-docs/Model/Inventory/Containers.js @@ -0,0 +1,7 @@ +Containers = new Meteor.Collection('containers'); + +Container = function(name, owner){ + this.name = name; + this.owner = owner; + this.isCarried = true; +} \ No newline at end of file diff --git a/rpg-docs/Model/Inventory/Items.js b/rpg-docs/Model/Inventory/Items.js new file mode 100644 index 00000000..ecce01c3 --- /dev/null +++ b/rpg-docs/Model/Inventory/Items.js @@ -0,0 +1,10 @@ +Items = new Meteor.Collection('items'); + +Item = function(name, container){ + this.name = name; + this.container = container; + this.quantity = 1; + this.weight = 0.0; + this.value = 0;//value in gold pieces + this.description = ""; +} \ No newline at end of file diff --git a/rpg-docs/Model/Utility/dice.js b/rpg-docs/Model/Utility/dice.js new file mode 100644 index 00000000..ea6cfe9b --- /dev/null +++ b/rpg-docs/Model/Utility/dice.js @@ -0,0 +1,44 @@ +roll = function (n, d){ + if(!isNaN(n)){ + //first digit is a number + if(d === undefined){ + d = n; + n = 1; + } + if(n > 500){ + console.log(n + " > 500, cannot lift that many dice to roll them"); + return; + } + var result = {sum: 0, rolls: []}; + for (var i = 0; i < n; i++){ + var roll = Math.floor(Random.fraction() * d + 1) + result.sum += roll; + result.rolls.push(roll); + } + return result; + } + console.log("rolling dice failed for inputs: ", n, d); + return {sum: 0, rolls: []}; +} + +rollDropLow = function(n, d, drop){ + var r = roll(n,d) + r.rolls.sort(function(a, b){return a-b}); //sort ascending + r.rolls.splice(0, drop); //remove the lowest elements + r.sum = 0; + for (var i = 0, l = r.rolls.length; i , l ; i++){ + sum += r.rolls[i]; + } + return r; +} + +rollDropHigh = function(n, d, drop){ + var r = roll(n,d) + r.rolls.sort(function(a, b){return b-a}); //sort descending + r.rolls.splice(0, drop); //remove the highest elements + r.sum = 0; + for (var i = 0, l = r.rolls.length; i , l ; i++){ + sum += r.rolls[i]; + } + return r; +} \ No newline at end of file diff --git a/rpg-docs/Routes/Routes.js b/rpg-docs/Routes/Routes.js new file mode 100644 index 00000000..3ee65e61 --- /dev/null +++ b/rpg-docs/Routes/Routes.js @@ -0,0 +1,20 @@ +Router.map( function () { + this.route('home', { + path: '/', + data: { characters: function(){ + console.log('id ' + Meteor.userId()); + return Characters.find({owner: Meteor.userId()}) + } + } + }); + + this.route('character', { + path: '/character/:_id', + notFoundTemplate: 'characterNotFound', + data: function() { + character = Characters.findOne({_id: this.params._id}); + if (character) character.items = Items.find({owner: this.params._id}); + return character; + } + }); +}); \ No newline at end of file diff --git a/rpg-docs/client/css/character.css b/rpg-docs/client/css/character.css new file mode 100644 index 00000000..9707afca --- /dev/null +++ b/rpg-docs/client/css/character.css @@ -0,0 +1,81 @@ +.flexContainer { + display: flex; + flex-wrap: wrap; +} + +#abilityScores { + text-align: center; + flex-basis: 120px; + flex-grow: 1; + max-width: 340px; +} + +/*Float boxes are indivisble, have shadows*/ +.floatBox{ + border: 2px solid black; + border-radius: 0px 0px 10px 10px; + padding: 5px; + margin: 5px; + background: white; +} + +/* headings in floatboxes */ +.floatBox h2{ + background: black; + color: white; + font-size: 1em; + margin: 0px -5px 0px -5px; + padding: 2px 15px; +} + +.floatBox h2:first-child{ + margin: -5px -5px 0px -5px; +} + +.floatBox.rounded { + border-radius: 10px; + display: inline-block; + text-align: center; +} + +/* Ability scores */ +.floatBox.ability { + border-radius: 10px; + width: 85px; + text-align: center; + margin: 5px 5px 20px 5px; + display: inline-block; +} + +.abilityName { + +} + +.abilityScore { + font-size: 2em; +} + +.abilityMod { + margin: 0 auto -15px; + padding: 2px; + border: 2px solid black; + border-radius: 5px; + background: white; + width: 40px; +} + +/* Stats */ +#armorClassBox { + width: 90px; + height: 100px; + background-image: url('/svg/ac.svg'); + background-repeat: no-repeat; + text-align: center; + display: flex; + flex-direction: column; + justify-content: center; +} + +.statValue { + font-size: 2em; +} \ No newline at end of file diff --git a/rpg-docs/client/css/general.css b/rpg-docs/client/css/general.css new file mode 100644 index 00000000..330b0f56 --- /dev/null +++ b/rpg-docs/client/css/general.css @@ -0,0 +1,7 @@ +root { + display: block; +} + +body { + font-family: sans-serif; +} \ No newline at end of file diff --git a/rpg-docs/client/views/character/abilities.html b/rpg-docs/client/views/character/abilities.html new file mode 100644 index 00000000..3e9740ff --- /dev/null +++ b/rpg-docs/client/views/character/abilities.html @@ -0,0 +1,68 @@ + \ No newline at end of file diff --git a/rpg-docs/client/views/character/character.html b/rpg-docs/client/views/character/character.html new file mode 100644 index 00000000..11dea4ed --- /dev/null +++ b/rpg-docs/client/views/character/character.html @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/rpg-docs/client/views/character/characterName.html b/rpg-docs/client/views/character/characterName.html new file mode 100644 index 00000000..553e4903 --- /dev/null +++ b/rpg-docs/client/views/character/characterName.html @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/rpg-docs/client/views/character/characterStats.html b/rpg-docs/client/views/character/characterStats.html new file mode 100644 index 00000000..ca3091c2 --- /dev/null +++ b/rpg-docs/client/views/character/characterStats.html @@ -0,0 +1,50 @@ + \ No newline at end of file diff --git a/rpg-docs/client/views/character/savesAndSkills.html b/rpg-docs/client/views/character/savesAndSkills.html new file mode 100644 index 00000000..b78886c9 --- /dev/null +++ b/rpg-docs/client/views/character/savesAndSkills.html @@ -0,0 +1,52 @@ + \ No newline at end of file diff --git a/rpg-docs/client/views/home/home.html b/rpg-docs/client/views/home/home.html new file mode 100644 index 00000000..562a9a94 --- /dev/null +++ b/rpg-docs/client/views/home/home.html @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/rpg-docs/client/views/home/home.js b/rpg-docs/client/views/home/home.js new file mode 100644 index 00000000..d365bf7e --- /dev/null +++ b/rpg-docs/client/views/home/home.js @@ -0,0 +1,11 @@ +Template.home.events({ + "click #addCharacter": function (event, template) { + Characters.insert(new Character(Meteor.userId())); + }, + "click #nukeCharacters": function(event, template){ + while(true){ + if(!Characters.findOne()) break; + Characters.remove(Characters.findOne()._id); + } + } +}); \ No newline at end of file diff --git a/rpg-docs/client/views/index.html b/rpg-docs/client/views/index.html new file mode 100644 index 00000000..b6554729 --- /dev/null +++ b/rpg-docs/client/views/index.html @@ -0,0 +1,4 @@ + + RPG Docs + + \ No newline at end of file diff --git a/rpg-docs/public/svg/ac.svg b/rpg-docs/public/svg/ac.svg new file mode 100644 index 00000000..001a1133 --- /dev/null +++ b/rpg-docs/public/svg/ac.svg @@ -0,0 +1,36 @@ + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/startup.sh b/startup.sh new file mode 100644 index 00000000..4c02c45e --- /dev/null +++ b/startup.sh @@ -0,0 +1,2 @@ +cd rpg-docs +export MONGO_URL=mongodb://thaum:pandas@linus.mongohq.com:10050/green_meteor \ No newline at end of file