From f1ddc43f9af2e98d6460316219db49378f0888e8 Mon Sep 17 00:00:00 2001 From: Russell Champoux Date: Wed, 11 Mar 2015 16:00:14 -0400 Subject: [PATCH] Rethinking my entire data storage and logic flow mechanisms. Storing everything in json files --- chance.js | 1980 +++++++++++++++++++++++++++++++ grimoire-core.js | 361 ++++++ index.html | 8 +- sources/APG.json | 10 + sources/APG/Rings.json | 22 + sources/APG/Rods.json | 47 + sources/APG/Spells.json | 70 ++ sources/APG/Wondrous Items.json | 72 ++ sources/CRB.json | 11 + sources/CRB/Rings.json | 50 + sources/CRB/Rods.json | 41 + sources/CRB/Spells.json | 258 ++++ sources/CRB/Wondrous Items.json | 396 +++++++ sources/UM.json | 5 + sources/UM/Spells.json | 28 + sources/sources.json | 3 + 16 files changed, 3361 insertions(+), 1 deletion(-) create mode 100644 chance.js create mode 100644 grimoire-core.js create mode 100644 sources/APG.json create mode 100644 sources/APG/Rings.json create mode 100644 sources/APG/Rods.json create mode 100644 sources/APG/Spells.json create mode 100644 sources/APG/Wondrous Items.json create mode 100644 sources/CRB.json create mode 100644 sources/CRB/Rings.json create mode 100644 sources/CRB/Rods.json create mode 100644 sources/CRB/Spells.json create mode 100644 sources/CRB/Wondrous Items.json create mode 100644 sources/UM.json create mode 100644 sources/UM/Spells.json create mode 100644 sources/sources.json diff --git a/chance.js b/chance.js new file mode 100644 index 0000000..a672318 --- /dev/null +++ b/chance.js @@ -0,0 +1,1980 @@ +// Chance.js 0.7.3 +// http://chancejs.com +// (c) 2013 Victor Quinn +// Chance may be freely distributed or modified under the MIT license. + +(function () { + + // Constants + var MAX_INT = 9007199254740992; + var MIN_INT = -MAX_INT; + var NUMBERS = '0123456789'; + var CHARS_LOWER = 'abcdefghijklmnopqrstuvwxyz'; + var CHARS_UPPER = CHARS_LOWER.toUpperCase(); + var HEX_POOL = NUMBERS + "abcdef"; + + // Cached array helpers + var slice = Array.prototype.slice; + + // Constructor + function Chance (seed) { + if (!(this instanceof Chance)) { + return new Chance(seed); + } + + // if user has provided a function, use that as the generator + if (typeof seed === 'function') { + this.random = seed; + return this; + } + + var seedling; + + if (arguments.length) { + // set a starting value of zero so we can add to it + this.seed = 0; + } + // otherwise, leave this.seed blank so that MT will recieve a blank + + for (var i = 0; i < arguments.length; i++) { + seedling = 0; + if (typeof arguments[i] === 'string') { + for (var j = 0; j < arguments[i].length; j++) { + seedling += (arguments[i].length - j) * arguments[i].charCodeAt(j); + } + } else { + seedling = arguments[i]; + } + this.seed += (arguments.length - i) * seedling; + } + + // If no generator function was provided, use our MT + this.mt = this.mersenne_twister(this.seed); + this.random = function () { + return this.mt.random(this.seed); + }; + + return this; + } + + Chance.prototype.VERSION = "0.7.3"; + + // Random helper functions + function initOptions(options, defaults) { + options || (options = {}); + + if (defaults) { + for (var i in defaults) { + if (typeof options[i] === 'undefined') { + options[i] = defaults[i]; + } + } + } + + return options; + } + + function testRange(test, errorMessage) { + if (test) { + throw new RangeError(errorMessage); + } + } + + /** + * Encode the input string with Base64. + */ + var base64 = function() { + throw new Error('No Base64 encoder available.'); + }; + + // Select proper Base64 encoder. + (function determineBase64Encoder() { + if (typeof btoa === 'function') { + base64 = btoa; + } else if (typeof Buffer === 'function') { + base64 = function(input) { + return new Buffer(input).toString('base64'); + }; + } + })(); + + // -- Basics -- + + Chance.prototype.bool = function (options) { + + // likelihood of success (true) + options = initOptions(options, {likelihood : 50}); + + testRange( + options.likelihood < 0 || options.likelihood > 100, + "Chance: Likelihood accepts values from 0 to 100." + ); + + return this.random() * 100 < options.likelihood; + }; + + Chance.prototype.character = function (options) { + options = initOptions(options); + + var symbols = "!@#$%^&*()[]", + letters, pool; + + testRange( + options.alpha && options.symbols, + "Chance: Cannot specify both alpha and symbols." + ); + + + if (options.casing === 'lower') { + letters = CHARS_LOWER; + } else if (options.casing === 'upper') { + letters = CHARS_UPPER; + } else { + letters = CHARS_LOWER + CHARS_UPPER; + } + + if (options.pool) { + pool = options.pool; + } else if (options.alpha) { + pool = letters; + } else if (options.symbols) { + pool = symbols; + } else { + pool = letters + NUMBERS + symbols; + } + + return pool.charAt(this.natural({max: (pool.length - 1)})); + }; + + // Note, wanted to use "float" or "double" but those are both JS reserved words. + + // Note, fixed means N OR LESS digits after the decimal. This because + // It could be 14.9000 but in JavaScript, when this is cast as a number, + // the trailing zeroes are dropped. Left to the consumer if trailing zeroes are + // needed + Chance.prototype.floating = function (options) { + var num; + + options = initOptions(options, {fixed : 4}); + var fixed = Math.pow(10, options.fixed); + + testRange( + options.fixed && options.precision, + "Chance: Cannot specify both fixed and precision." + ); + + var max = MAX_INT / fixed; + var min = -max; + + testRange( + options.min && options.fixed && options.min < min, + "Chance: Min specified is out of range with fixed. Min should be, at least, " + min + ); + testRange( + options.max && options.fixed && options.max > max, + "Chance: Max specified is out of range with fixed. Max should be, at most, " + max + ); + + options = initOptions(options, {min : min, max : max}); + + // Todo - Make this work! + // options.precision = (typeof options.precision !== "undefined") ? options.precision : false; + + num = this.integer({min: options.min * fixed, max: options.max * fixed}); + var num_fixed = (num / fixed).toFixed(options.fixed); + + return parseFloat(num_fixed); + }; + + // NOTE the max and min are INCLUDED in the range. So: + // + // chance.natural({min: 1, max: 3}); + // + // would return either 1, 2, or 3. + + Chance.prototype.integer = function (options) { + + // 9007199254740992 (2^53) is the max integer number in JavaScript + // See: http://vq.io/132sa2j + options = initOptions(options, {min: MIN_INT, max: MAX_INT}); + + testRange(options.min > options.max, "Chance: Min cannot be greater than Max."); + + return Math.floor(this.random() * (options.max - options.min + 1) + options.min); + }; + + Chance.prototype.natural = function (options) { + options = initOptions(options, {min: 0, max: MAX_INT}); + return this.integer(options); + }; + + Chance.prototype.string = function (options) { + options = initOptions(options); + + var length = options.length || this.natural({min: 5, max: 20}), + pool = options.pool, + text = this.n(this.character, length, {pool: pool}); + + return text.join(""); + }; + + // -- End Basics -- + + // -- Helpers -- + + Chance.prototype.capitalize = function (word) { + return word.charAt(0).toUpperCase() + word.substr(1); + }; + + Chance.prototype.mixin = function (obj) { + for (var func_name in obj) { + Chance.prototype[func_name] = obj[func_name]; + } + return this; + }; + + // Given a function that generates something random and a number of items to generate, + // return an array of items where none repeat. + Chance.prototype.unique = function(fn, num, options) { + options = initOptions(options, { + // Default comparator to check that val is not already in arr. + // Should return `false` if item not in array, `true` otherwise + comparator: function(arr, val) { + return arr.indexOf(val) !== -1; + } + }); + + var arr = [], count = 0, result, MAX_DUPLICATES = num * 50, params = slice.call(arguments, 2); + + while (arr.length < num) { + result = fn.apply(this, params); + if (!options.comparator(arr, result)) { + arr.push(result); + // reset count when unique found + count = 0; + } + + if (++count > MAX_DUPLICATES) { + throw new RangeError("Chance: num is likely too large for sample set"); + } + } + return arr; + }; + + /** + * Gives an array of n random terms + * @param fn the function that generates something random + * @param n number of terms to generate + * There can be more parameters after these. All additional parameters are provided to the given function + */ + Chance.prototype.n = function(fn, n) { + if (typeof n === 'undefined') { + n = 1; + } + var i = n, arr = [], params = slice.call(arguments, 2); + + // Providing a negative count should result in a noop. + i = Math.max( 0, i ); + + for (null; i--; null) { + arr.push(fn.apply(this, params)); + } + + return arr; + }; + + // H/T to SO for this one: http://vq.io/OtUrZ5 + Chance.prototype.pad = function (number, width, pad) { + // Default pad to 0 if none provided + pad = pad || '0'; + // Convert number to a string + number = number + ''; + return number.length >= width ? number : new Array(width - number.length + 1).join(pad) + number; + }; + + Chance.prototype.pick = function (arr, count) { + if (arr.length === 0) { + throw new RangeError("Chance: Cannot pick() from an empty array"); + } + if (!count || count === 1) { + return arr[this.natural({max: arr.length - 1})]; + } else { + return this.shuffle(arr).slice(0, count); + } + }; + + Chance.prototype.shuffle = function (arr) { + var old_array = arr.slice(0), + new_array = [], + j = 0, + length = Number(old_array.length); + + for (var i = 0; i < length; i++) { + // Pick a random index from the array + j = this.natural({max: old_array.length - 1}); + // Add it to the new array + new_array[i] = old_array[j]; + // Remove that element from the original array + old_array.splice(j, 1); + } + + return new_array; + }; + + // Returns a single item from an array with relative weighting of odds + Chance.prototype.weighted = function(arr, weights) { + if (arr.length !== weights.length) { + throw new RangeError("Chance: length of array and weights must match"); + } + + // Handle weights that are less or equal to zero. + for (var weightIndex = weights.length - 1; weightIndex >= 0; --weightIndex) { + // If the weight is less or equal to zero, remove it and the value. + if (weights[weightIndex] <= 0) { + arr.splice(weightIndex,1); + weights.splice(weightIndex,1); + } + } + + // If any of the weights are less than 1, we want to scale them up to whole + // numbers for the rest of this logic to work + if (weights.some(function(weight) { return weight < 1; })) { + var min = weights.reduce(function(min, weight) { + return (weight < min) ? weight : min; + }, weights[0]); + + var scaling_factor = 1 / min; + + weights = weights.map(function(weight) { + return weight * scaling_factor; + }); + } + + var sum = weights.reduce(function(total, weight) { + return total + weight; + }, 0); + + // get an index + var selected = this.natural({ min: 1, max: sum }); + + var total = 0; + var chosen; + // Using some() here so we can bail as soon as we get our match + weights.some(function(weight, index) { + if (selected <= total + weight) { + chosen = arr[index]; + return true; + } + total += weight; + return false; + }); + + return chosen; + }; + + // -- End Helpers -- + + // -- Text -- + + Chance.prototype.paragraph = function (options) { + options = initOptions(options); + + var sentences = options.sentences || this.natural({min: 3, max: 7}), + sentence_array = this.n(this.sentence, sentences); + + return sentence_array.join(' '); + }; + + // Could get smarter about this than generating random words and + // chaining them together. Such as: http://vq.io/1a5ceOh + Chance.prototype.sentence = function (options) { + options = initOptions(options); + + var words = options.words || this.natural({min: 12, max: 18}), + text, word_array = this.n(this.word, words); + + text = word_array.join(' '); + + // Capitalize first letter of sentence, add period at end + text = this.capitalize(text) + '.'; + + return text; + }; + + Chance.prototype.syllable = function (options) { + options = initOptions(options); + + var length = options.length || this.natural({min: 2, max: 3}), + consonants = 'bcdfghjklmnprstvwz', // consonants except hard to speak ones + vowels = 'aeiou', // vowels + all = consonants + vowels, // all + text = '', + chr; + + // I'm sure there's a more elegant way to do this, but this works + // decently well. + for (var i = 0; i < length; i++) { + if (i === 0) { + // First character can be anything + chr = this.character({pool: all}); + } else if (consonants.indexOf(chr) === -1) { + // Last character was a vowel, now we want a consonant + chr = this.character({pool: consonants}); + } else { + // Last character was a consonant, now we want a vowel + chr = this.character({pool: vowels}); + } + + text += chr; + } + + return text; + }; + + Chance.prototype.word = function (options) { + options = initOptions(options); + + testRange( + options.syllables && options.length, + "Chance: Cannot specify both syllables AND length." + ); + + var syllables = options.syllables || this.natural({min: 1, max: 3}), + text = ''; + + if (options.length) { + // Either bound word by length + do { + text += this.syllable(); + } while (text.length < options.length); + text = text.substring(0, options.length); + } else { + // Or by number of syllables + for (var i = 0; i < syllables; i++) { + text += this.syllable(); + } + } + return text; + }; + + // -- End Text -- + + // -- Person -- + + Chance.prototype.age = function (options) { + options = initOptions(options); + var ageRange; + + switch (options.type) { + case 'child': + ageRange = {min: 1, max: 12}; + break; + case 'teen': + ageRange = {min: 13, max: 19}; + break; + case 'adult': + ageRange = {min: 18, max: 65}; + break; + case 'senior': + ageRange = {min: 65, max: 100}; + break; + case 'all': + ageRange = {min: 1, max: 100}; + break; + default: + ageRange = {min: 18, max: 65}; + break; + } + + return this.natural(ageRange); + }; + + Chance.prototype.birthday = function (options) { + options = initOptions(options, { + year: (new Date().getFullYear() - this.age(options)) + }); + + return this.date(options); + }; + + // CPF; ID to identify taxpayers in Brazil + Chance.prototype.cpf = function () { + var n = this.n(this.natural, 9, { max: 9 }); + var d1 = n[8]*2+n[7]*3+n[6]*4+n[5]*5+n[4]*6+n[3]*7+n[2]*8+n[1]*9+n[0]*10; + d1 = 11 - (d1 % 11); + if (d1>=10) { + d1 = 0; + } + var d2 = d1*2+n[8]*3+n[7]*4+n[6]*5+n[5]*6+n[4]*7+n[3]*8+n[2]*9+n[1]*10+n[0]*11; + d2 = 11 - (d2 % 11); + if (d2>=10) { + d2 = 0; + } + return ''+n[0]+n[1]+n[2]+'.'+n[3]+n[4]+n[5]+'.'+n[6]+n[7]+n[8]+'-'+d1+d2; + }; + + Chance.prototype.first = function (options) { + options = initOptions(options, {gender: this.gender()}); + return this.pick(this.get("firstNames")[options.gender.toLowerCase()]); + }; + + Chance.prototype.gender = function () { + return this.pick(['Male', 'Female']); + }; + + Chance.prototype.last = function () { + return this.pick(this.get("lastNames")); + }; + + Chance.prototype.name = function (options) { + options = initOptions(options); + + var first = this.first(options), + last = this.last(), + name; + + if (options.middle) { + name = first + ' ' + this.first(options) + ' ' + last; + } else if (options.middle_initial) { + name = first + ' ' + this.character({alpha: true, casing: 'upper'}) + '. ' + last; + } else { + name = first + ' ' + last; + } + + if (options.prefix) { + name = this.prefix(options) + ' ' + name; + } + + if (options.suffix) { + name = name + ' ' + this.suffix(options); + } + + return name; + }; + + // Return the list of available name prefixes based on supplied gender. + Chance.prototype.name_prefixes = function (gender) { + gender = gender || "all"; + gender = gender.toLowerCase(); + + var prefixes = [ + { name: 'Doctor', abbreviation: 'Dr.' } + ]; + + if (gender === "male" || gender === "all") { + prefixes.push({ name: 'Mister', abbreviation: 'Mr.' }); + } + + if (gender === "female" || gender === "all") { + prefixes.push({ name: 'Miss', abbreviation: 'Miss' }); + prefixes.push({ name: 'Misses', abbreviation: 'Mrs.' }); + } + + return prefixes; + }; + + // Alias for name_prefix + Chance.prototype.prefix = function (options) { + return this.name_prefix(options); + }; + + Chance.prototype.name_prefix = function (options) { + options = initOptions(options, { gender: "all" }); + return options.full ? + this.pick(this.name_prefixes(options.gender)).name : + this.pick(this.name_prefixes(options.gender)).abbreviation; + }; + + Chance.prototype.ssn = function (options) { + options = initOptions(options, {ssnFour: false, dashes: true}); + var ssn_pool = "1234567890", + ssn, + dash = options.dashes ? '-' : ''; + + if(!options.ssnFour) { + ssn = this.string({pool: ssn_pool, length: 3}) + dash + + this.string({pool: ssn_pool, length: 2}) + dash + + this.string({pool: ssn_pool, length: 4}); + } else { + ssn = this.string({pool: ssn_pool, length: 4}); + } + return ssn; + }; + + // Return the list of available name suffixes + Chance.prototype.name_suffixes = function () { + var suffixes = [ + { name: 'Doctor of Osteopathic Medicine', abbreviation: 'D.O.' }, + { name: 'Doctor of Philosophy', abbreviation: 'Ph.D.' }, + { name: 'Esquire', abbreviation: 'Esq.' }, + { name: 'Junior', abbreviation: 'Jr.' }, + { name: 'Juris Doctor', abbreviation: 'J.D.' }, + { name: 'Master of Arts', abbreviation: 'M.A.' }, + { name: 'Master of Business Administration', abbreviation: 'M.B.A.' }, + { name: 'Master of Science', abbreviation: 'M.S.' }, + { name: 'Medical Doctor', abbreviation: 'M.D.' }, + { name: 'Senior', abbreviation: 'Sr.' }, + { name: 'The Third', abbreviation: 'III' }, + { name: 'The Fourth', abbreviation: 'IV' } + ]; + return suffixes; + }; + + // Alias for name_suffix + Chance.prototype.suffix = function (options) { + return this.name_suffix(options); + }; + + Chance.prototype.name_suffix = function (options) { + options = initOptions(options); + return options.full ? + this.pick(this.name_suffixes()).name : + this.pick(this.name_suffixes()).abbreviation; + }; + + // -- End Person -- + + // -- Mobile -- + // Android GCM Registration ID + Chance.prototype.android_id = function () { + return "APA91" + this.string({ pool: "0123456789abcefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_", length: 178 }); + }; + + // Apple Push Token + Chance.prototype.apple_token = function () { + return this.string({ pool: "abcdef1234567890", length: 64 }); + }; + + // Windows Phone 8 ANID2 + Chance.prototype.wp8_anid2 = function () { + return base64( this.hash( { length : 32 } ) ); + }; + + // Windows Phone 7 ANID + Chance.prototype.wp7_anid = function () { + return 'A=' + this.guid().replace(/-/g, '').toUpperCase() + '&E=' + this.hash({ length:3 }) + '&W=' + this.integer({ min:0, max:9 }); + }; + + // BlackBerry Device PIN + Chance.prototype.bb_pin = function () { + return this.hash({ length: 8 }); + }; + + // -- End Mobile -- + + // -- Web -- + Chance.prototype.color = function (options) { + function gray(value, delimiter) { + return [value, value, value].join(delimiter || ''); + } + + options = initOptions(options, {format: this.pick(['hex', 'shorthex', 'rgb', '0x']), grayscale: false, casing: 'lower'}); + var isGrayscale = options.grayscale; + var colorValue; + + if (options.format === 'hex') { + colorValue = '#' + (isGrayscale ? gray(this.hash({length: 2})) : this.hash({length: 6})); + + } else if (options.format === 'shorthex') { + colorValue = '#' + (isGrayscale ? gray(this.hash({length: 1})) : this.hash({length: 3})); + + } else if (options.format === 'rgb') { + if (isGrayscale) { + colorValue = 'rgb(' + gray(this.natural({max: 255}), ',') + ')'; + } else { + colorValue = 'rgb(' + this.natural({max: 255}) + ',' + this.natural({max: 255}) + ',' + this.natural({max: 255}) + ')'; + } + } else if (options.format === '0x') { + colorValue = '0x' + (isGrayscale ? gray(this.hash({length: 2})) : this.hash({length: 6})); + } else { + throw new Error('Invalid format provided. Please provide one of "hex", "shorthex", "rgb" or "0x".'); + } + + if (options.casing === 'upper' ) { + colorValue = colorValue.toUpperCase(); + } + + return colorValue; + }; + + Chance.prototype.domain = function (options) { + options = initOptions(options); + return this.word() + '.' + (options.tld || this.tld()); + }; + + Chance.prototype.email = function (options) { + options = initOptions(options); + return this.word({length: options.length}) + '@' + (options.domain || this.domain()); + }; + + Chance.prototype.fbid = function () { + return parseInt('10000' + this.natural({max: 100000000000}), 10); + }; + + Chance.prototype.google_analytics = function () { + var account = this.pad(this.natural({max: 999999}), 6); + var property = this.pad(this.natural({max: 99}), 2); + + return 'UA-' + account + '-' + property; + }; + + Chance.prototype.hashtag = function () { + return '#' + this.word(); + }; + + Chance.prototype.ip = function () { + // Todo: This could return some reserved IPs. See http://vq.io/137dgYy + // this should probably be updated to account for that rare as it may be + return this.natural({max: 255}) + '.' + + this.natural({max: 255}) + '.' + + this.natural({max: 255}) + '.' + + this.natural({max: 255}); + }; + + Chance.prototype.ipv6 = function () { + var ip_addr = this.n(this.hash, 8, {length: 4}); + + return ip_addr.join(":"); + }; + + Chance.prototype.klout = function () { + return this.natural({min: 1, max: 99}); + }; + + Chance.prototype.tlds = function () { + return ['com', 'org', 'edu', 'gov', 'co.uk', 'net', 'io']; + }; + + Chance.prototype.tld = function () { + return this.pick(this.tlds()); + }; + + Chance.prototype.twitter = function () { + return '@' + this.word(); + }; + + Chance.prototype.url = function (options) { + options = initOptions(options, { protocol: "http", domain: this.domain(options), domain_prefix: "", path: this.word(), extensions: []}); + + var extension = options.extensions.length > 0 ? "." + this.pick(options.extensions) : ""; + var domain = options.domain_prefix ? options.domain_prefix + "." + options.domain : options.domain; + + return options.protocol + "://" + domain + "/" + options.path + extension; + }; + + // -- End Web -- + + // -- Location -- + + Chance.prototype.address = function (options) { + options = initOptions(options); + return this.natural({min: 5, max: 2000}) + ' ' + this.street(options); + }; + + Chance.prototype.altitude = function (options) { + options = initOptions(options, {fixed : 5, max: 8848}); + return this.floating({min: 0, max: options.max, fixed: options.fixed}); + }; + + Chance.prototype.areacode = function (options) { + options = initOptions(options, {parens : true}); + // Don't want area codes to start with 1, or have a 9 as the second digit + var areacode = this.natural({min: 2, max: 9}).toString() + + this.natural({min: 0, max: 8}).toString() + + this.natural({min: 0, max: 9}).toString(); + + return options.parens ? '(' + areacode + ')' : areacode; + }; + + Chance.prototype.city = function () { + return this.capitalize(this.word({syllables: 3})); + }; + + Chance.prototype.coordinates = function (options) { + options = initOptions(options); + return this.latitude(options) + ', ' + this.longitude(options); + }; + + Chance.prototype.countries = function () { + return this.get("countries"); + }; + + Chance.prototype.country = function (options) { + options = initOptions(options); + var country = this.pick(this.countries()); + return options.full ? country.name : country.abbreviation; + }; + + Chance.prototype.depth = function (options) { + options = initOptions(options, {fixed: 5, min: -2550}); + return this.floating({min: options.min, max: 0, fixed: options.fixed}); + }; + + Chance.prototype.geohash = function (options) { + options = initOptions(options, { length: 7 }); + return this.string({ length: options.length, pool: '0123456789bcdefghjkmnpqrstuvwxyz' }); + }; + + Chance.prototype.geojson = function (options) { + options = initOptions(options); + return this.latitude(options) + ', ' + this.longitude(options) + ', ' + this.altitude(options); + }; + + Chance.prototype.latitude = function (options) { + options = initOptions(options, {fixed: 5, min: -90, max: 90}); + return this.floating({min: options.min, max: options.max, fixed: options.fixed}); + }; + + Chance.prototype.longitude = function (options) { + options = initOptions(options, {fixed: 5, min: -180, max: 180}); + return this.floating({min: options.min, max: options.max, fixed: options.fixed}); + }; + + Chance.prototype.phone = function (options) { + var self = this, + numPick, + ukNum = function (parts) { + var section = []; + //fills the section part of the phone number with random numbers. + parts.sections.forEach(function(n) { + section.push(self.string({ pool: '0123456789', length: n})); + }); + return parts.area + section.join(' '); + }; + options = initOptions(options, { + formatted: true, + country: 'us', + mobile: false + }); + if (!options.formatted) { + options.parens = false; + } + var phone; + switch (options.country) { + case 'fr': + if (!options.mobile) { + numPick = this.pick([ + // Valid zone and département codes. + '01' + this.pick(['30', '34', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '53', '55', '56', '58', '60', '64', '69', '70', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83']) + self.string({ pool: '0123456789', length: 6}), + '02' + this.pick(['14', '18', '22', '23', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '40', '41', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '56', '57', '61', '62', '69', '72', '76', '77', '78', '85', '90', '96', '97', '98', '99']) + self.string({ pool: '0123456789', length: 6}), + '03' + this.pick(['10', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '39', '44', '45', '51', '52', '54', '55', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90']) + self.string({ pool: '0123456789', length: 6}), + '04' + this.pick(['11', '13', '15', '20', '22', '26', '27', '30', '32', '34', '37', '42', '43', '44', '50', '56', '57', '63', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '88', '89', '90', '91', '92', '93', '94', '95', '97', '98']) + self.string({ pool: '0123456789', length: 6}), + '05' + this.pick(['08', '16', '17', '19', '24', '31', '32', '33', '34', '35', '40', '45', '46', '47', '49', '53', '55', '56', '57', '58', '59', '61', '62', '63', '64', '65', '67', '79', '81', '82', '86', '87', '90', '94']) + self.string({ pool: '0123456789', length: 6}), + '09' + self.string({ pool: '0123456789', length: 8}), + ]); + phone = options.formatted ? numPick.match(/../g).join(' ') : numPick; + } else { + numPick = this.pick(['06', '07']) + self.string({ pool: '0123456789', length: 8}); + phone = options.formatted ? numPick.match(/../g).join(' ') : numPick; + } + break; + case 'uk': + if (!options.mobile) { + numPick = this.pick([ + //valid area codes of major cities/counties followed by random numbers in required format. + { area: '01' + this.character({ pool: '234569' }) + '1 ', sections: [3,4] }, + { area: '020 ' + this.character({ pool: '378' }), sections: [3,4] }, + { area: '023 ' + this.character({ pool: '89' }), sections: [3,4] }, + { area: '024 7', sections: [3,4] }, + { area: '028 ' + this.pick(['25','28','37','71','82','90','92','95']), sections: [2,4] }, + { area: '012' + this.pick(['04','08','54','76','97','98']) + ' ', sections: [5] }, + { area: '013' + this.pick(['63','64','84','86']) + ' ', sections: [5] }, + { area: '014' + this.pick(['04','20','60','61','80','88']) + ' ', sections: [5] }, + { area: '015' + this.pick(['24','27','62','66']) + ' ', sections: [5] }, + { area: '016' + this.pick(['06','29','35','47','59','95']) + ' ', sections: [5] }, + { area: '017' + this.pick(['26','44','50','68']) + ' ', sections: [5] }, + { area: '018' + this.pick(['27','37','84','97']) + ' ', sections: [5] }, + { area: '019' + this.pick(['00','05','35','46','49','63','95']) + ' ', sections: [5] } + ]); + phone = options.formatted ? ukNum(numPick) : ukNum(numPick).replace(' ', '', 'g'); + } else { + numPick = this.pick([ + { area: '07' + this.pick(['4','5','7','8','9']), sections: [2,6] }, + { area: '07624 ', sections: [6] } + ]); + phone = options.formatted ? ukNum(numPick) : ukNum(numPick).replace(' ', ''); + } + break; + case 'us': + var areacode = this.areacode(options).toString(); + var exchange = this.natural({ min: 2, max: 9 }).toString() + + this.natural({ min: 0, max: 9 }).toString() + + this.natural({ min: 0, max: 9 }).toString(); + var subscriber = this.natural({ min: 1000, max: 9999 }).toString(); // this could be random [0-9]{4} + phone = options.formatted ? areacode + ' ' + exchange + '-' + subscriber : areacode + exchange + subscriber; + } + return phone; + }; + + Chance.prototype.postal = function () { + // Postal District + var pd = this.character({pool: "XVTSRPNKLMHJGECBA"}); + // Forward Sortation Area (FSA) + var fsa = pd + this.natural({max: 9}) + this.character({alpha: true, casing: "upper"}); + // Local Delivery Unut (LDU) + var ldu = this.natural({max: 9}) + this.character({alpha: true, casing: "upper"}) + this.natural({max: 9}); + + return fsa + " " + ldu; + }; + + Chance.prototype.provinces = function () { + return this.get("provinces"); + }; + + Chance.prototype.province = function (options) { + return (options && options.full) ? + this.pick(this.provinces()).name : + this.pick(this.provinces()).abbreviation; + }; + + Chance.prototype.state = function (options) { + return (options && options.full) ? + this.pick(this.states(options)).name : + this.pick(this.states(options)).abbreviation; + }; + + Chance.prototype.states = function (options) { + options = initOptions(options); + + var states, + us_states_and_dc = this.get("us_states_and_dc"), + territories = this.get("territories"), + armed_forces = this.get("armed_forces"); + + states = us_states_and_dc; + + if (options.territories) { + states = states.concat(territories); + } + if (options.armed_forces) { + states = states.concat(armed_forces); + } + + return states; + }; + + Chance.prototype.street = function (options) { + options = initOptions(options); + + var street = this.word({syllables: 2}); + street = this.capitalize(street); + street += ' '; + street += options.short_suffix ? + this.street_suffix().abbreviation : + this.street_suffix().name; + return street; + }; + + Chance.prototype.street_suffix = function () { + return this.pick(this.street_suffixes()); + }; + + Chance.prototype.street_suffixes = function () { + // These are the most common suffixes. + return this.get("street_suffixes"); + }; + + // Note: only returning US zip codes, internationalization will be a whole + // other beast to tackle at some point. + Chance.prototype.zip = function (options) { + var zip = this.n(this.natural, 5, {max: 9}); + + if (options && options.plusfour === true) { + zip.push('-'); + zip = zip.concat(this.n(this.natural, 4, {max: 9})); + } + + return zip.join(""); + }; + + // -- End Location -- + + // -- Time + + Chance.prototype.ampm = function () { + return this.bool() ? 'am' : 'pm'; + }; + + Chance.prototype.date = function (options) { + var date_string, date; + + // If interval is specified we ignore preset + if(options && (options.min || options.max)) { + options = initOptions(options, { + american: true, + string: false + }); + var min = typeof options.min !== "undefined" ? options.min.getTime() : 1; + // 100,000,000 days measured relative to midnight at the beginning of 01 January, 1970 UTC. http://es5.github.io/#x15.9.1.1 + var max = typeof options.max !== "undefined" ? options.max.getTime() : 8640000000000000; + + date = new Date(this.natural({min: min, max: max})); + } else { + var m = this.month({raw: true}); + + options = initOptions(options, { + year: parseInt(this.year(), 10), + // Necessary to subtract 1 because Date() 0-indexes month but not day or year + // for some reason. + month: m.numeric - 1, + day: this.natural({min: 1, max: m.days}), + hour: this.hour(), + minute: this.minute(), + second: this.second(), + millisecond: this.millisecond(), + american: true, + string: false + }); + + date = new Date(options.year, options.month, options.day, options.hour, options.minute, options.second, options.millisecond); + } + + if (options.american) { + // Adding 1 to the month is necessary because Date() 0-indexes + // months but not day for some odd reason. + date_string = (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear(); + } else { + date_string = date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear(); + } + + return options.string ? date_string : date; + }; + + Chance.prototype.hammertime = function (options) { + return this.date(options).getTime(); + }; + + Chance.prototype.hour = function (options) { + options = initOptions(options, {min: 1, max: options && options.twentyfour ? 24 : 12}); + + testRange(options.min < 1, "Chance: Min cannot be less than 1."); + testRange(options.twentyfour && options.max > 24, "Chance: Max cannot be greater than 24 for twentyfour option."); + testRange(!options.twentyfour && options.max > 12, "Chance: Max cannot be greater than 12."); + testRange(options.min > options.max, "Chance: Min cannot be greater than Max."); + + return this.natural({min: options.min, max: options.max}); + }; + + Chance.prototype.millisecond = function () { + return this.natural({max: 999}); + }; + + Chance.prototype.minute = Chance.prototype.second = function (options) { + options = initOptions(options, {min: 0, max: 59}); + + testRange(options.min < 0, "Chance: Min cannot be less than 0."); + testRange(options.max > 59, "Chance: Max cannot be greater than 59."); + testRange(options.min > options.max, "Chance: Min cannot be greater than Max."); + + return this.natural({min: options.min, max: options.max}); + }; + + Chance.prototype.month = function (options) { + options = initOptions(options, {min: 1, max: 12}); + + testRange(options.min < 1, "Chance: Min cannot be less than 1."); + testRange(options.max > 12, "Chance: Max cannot be greater than 12."); + testRange(options.min > options.max, "Chance: Min cannot be greater than Max."); + + var month = this.pick(this.months().slice(options.min - 1, options.max)); + return options.raw ? month : month.name; + }; + + Chance.prototype.months = function () { + return this.get("months"); + }; + + Chance.prototype.second = function () { + return this.natural({max: 59}); + }; + + Chance.prototype.timestamp = function () { + return this.natural({min: 1, max: parseInt(new Date().getTime() / 1000, 10)}); + }; + + Chance.prototype.year = function (options) { + // Default to current year as min if none specified + options = initOptions(options, {min: new Date().getFullYear()}); + + // Default to one century after current year as max if none specified + options.max = (typeof options.max !== "undefined") ? options.max : options.min + 100; + + return this.natural(options).toString(); + }; + + // -- End Time + + // -- Finance -- + + Chance.prototype.cc = function (options) { + options = initOptions(options); + + var type, number, to_generate; + + type = (options.type) ? + this.cc_type({ name: options.type, raw: true }) : + this.cc_type({ raw: true }); + + number = type.prefix.split(""); + to_generate = type.length - type.prefix.length - 1; + + // Generates n - 1 digits + number = number.concat(this.n(this.integer, to_generate, {min: 0, max: 9})); + + // Generates the last digit according to Luhn algorithm + number.push(this.luhn_calculate(number.join(""))); + + return number.join(""); + }; + + Chance.prototype.cc_types = function () { + // http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29 + return this.get("cc_types"); + }; + + Chance.prototype.cc_type = function (options) { + options = initOptions(options); + var types = this.cc_types(), + type = null; + + if (options.name) { + for (var i = 0; i < types.length; i++) { + // Accept either name or short_name to specify card type + if (types[i].name === options.name || types[i].short_name === options.name) { + type = types[i]; + break; + } + } + if (type === null) { + throw new Error("Credit card type '" + options.name + "'' is not supported"); + } + } else { + type = this.pick(types); + } + + return options.raw ? type : type.name; + }; + + //return all world currency by ISO 4217 + Chance.prototype.currency_types = function () { + return this.get("currency_types"); + }; + + //return random world currency by ISO 4217 + Chance.prototype.currency = function () { + return this.pick(this.currency_types()); + }; + + //Return random correct currency exchange pair (e.g. EUR/USD) or array of currency code + Chance.prototype.currency_pair = function (returnAsString) { + var currencies = this.unique(this.currency, 2, { + comparator: function(arr, val) { + + return arr.reduce(function(acc, item) { + // If a match has been found, short circuit check and just return + return acc || (item.code === val.code); + }, false); + } + }); + + if (returnAsString) { + return currencies[0] + '/' + currencies[1]; + } else { + return currencies; + } + }; + + Chance.prototype.dollar = function (options) { + // By default, a somewhat more sane max for dollar than all available numbers + options = initOptions(options, {max : 10000, min : 0}); + + var dollar = this.floating({min: options.min, max: options.max, fixed: 2}).toString(), + cents = dollar.split('.')[1]; + + if (cents === undefined) { + dollar += '.00'; + } else if (cents.length < 2) { + dollar = dollar + '0'; + } + + if (dollar < 0) { + return '-$' + dollar.replace('-', ''); + } else { + return '$' + dollar; + } + }; + + Chance.prototype.exp = function (options) { + options = initOptions(options); + var exp = {}; + + exp.year = this.exp_year(); + + // If the year is this year, need to ensure month is greater than the + // current month or this expiration will not be valid + if (exp.year === (new Date().getFullYear())) { + exp.month = this.exp_month({future: true}); + } else { + exp.month = this.exp_month(); + } + + return options.raw ? exp : exp.month + '/' + exp.year; + }; + + Chance.prototype.exp_month = function (options) { + options = initOptions(options); + var month, month_int, + curMonth = new Date().getMonth(); + + if (options.future) { + do { + month = this.month({raw: true}).numeric; + month_int = parseInt(month, 10); + } while (month_int < curMonth); + } else { + month = this.month({raw: true}).numeric; + } + + return month; + }; + + Chance.prototype.exp_year = function () { + return this.year({max: new Date().getFullYear() + 10}); + }; + + // -- End Finance + + // -- Miscellaneous -- + + // Dice - For all the board game geeks out there, myself included ;) + function diceFn (range) { + return function () { + return this.natural(range); + }; + } + Chance.prototype.d4 = diceFn({min: 1, max: 4}); + Chance.prototype.d6 = diceFn({min: 1, max: 6}); + Chance.prototype.d8 = diceFn({min: 1, max: 8}); + Chance.prototype.d10 = diceFn({min: 1, max: 10}); + Chance.prototype.d12 = diceFn({min: 1, max: 12}); + Chance.prototype.d20 = diceFn({min: 1, max: 20}); + Chance.prototype.d30 = diceFn({min: 1, max: 30}); + Chance.prototype.d100 = diceFn({min: 1, max: 100}); + + Chance.prototype.rpg = function (thrown, options) { + options = initOptions(options); + if (thrown === null) { + throw new Error("A type of die roll must be included"); + } else { + var bits = thrown.toLowerCase().split("d"), + rolls = []; + + if (bits.length !== 2 || !parseInt(bits[0], 10) || !parseInt(bits[1], 10)) { + throw new Error("Invalid format provided. Please provide #d# where the first # is the number of dice to roll, the second # is the max of each die"); + } + for (var i = bits[0]; i > 0; i--) { + rolls[i - 1] = this.natural({min: 1, max: bits[1]}); + } + return (typeof options.sum !== 'undefined' && options.sum) ? rolls.reduce(function (p, c) { return p + c; }) : rolls; + } + }; + + // Guid + Chance.prototype.guid = function (options) { + options = initOptions(options, { version: 5 }); + + var guid_pool = "abcdef1234567890", + variant_pool = "ab89", + guid = this.string({ pool: guid_pool, length: 8 }) + '-' + + this.string({ pool: guid_pool, length: 4 }) + '-' + + // The Version + options.version + + this.string({ pool: guid_pool, length: 3 }) + '-' + + // The Variant + this.string({ pool: variant_pool, length: 1 }) + + this.string({ pool: guid_pool, length: 3 }) + '-' + + this.string({ pool: guid_pool, length: 12 }); + return guid; + }; + + // Hash + Chance.prototype.hash = function (options) { + options = initOptions(options, {length : 40, casing: 'lower'}); + var pool = options.casing === 'upper' ? HEX_POOL.toUpperCase() : HEX_POOL; + return this.string({pool: pool, length: options.length}); + }; + + Chance.prototype.luhn_check = function (num) { + var str = num.toString(); + var checkDigit = +str.substring(str.length - 1); + return checkDigit === this.luhn_calculate(+str.substring(0, str.length - 1)); + }; + + Chance.prototype.luhn_calculate = function (num) { + var digits = num.toString().split("").reverse(); + var sum = 0; + var digit; + + for (var i = 0, l = digits.length; l > i; ++i) { + digit = +digits[i]; + if (i % 2 === 0) { + digit *= 2; + if (digit > 9) { + digit -= 9; + } + } + sum += digit; + } + return (sum * 9) % 10; + }; + + + var data = { + + firstNames: { + "male": ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Charles", "Thomas", "Christopher", "Daniel", "Matthew", "George", "Donald", "Anthony", "Paul", "Mark", "Edward", "Steven", "Kenneth", "Andrew", "Brian", "Joshua", "Kevin", "Ronald", "Timothy", "Jason", "Jeffrey", "Frank", "Gary", "Ryan", "Nicholas", "Eric", "Stephen", "Jacob", "Larry", "Jonathan", "Scott", "Raymond", "Justin", "Brandon", "Gregory", "Samuel", "Benjamin", "Patrick", "Jack", "Henry", "Walter", "Dennis", "Jerry", "Alexander", "Peter", "Tyler", "Douglas", "Harold", "Aaron", "Jose", "Adam", "Arthur", "Zachary", "Carl", "Nathan", "Albert", "Kyle", "Lawrence", "Joe", "Willie", "Gerald", "Roger", "Keith", "Jeremy", "Terry", "Harry", "Ralph", "Sean", "Jesse", "Roy", "Louis", "Billy", "Austin", "Bruce", "Eugene", "Christian", "Bryan", "Wayne", "Russell", "Howard", "Fred", "Ethan", "Jordan", "Philip", "Alan", "Juan", "Randy", "Vincent", "Bobby", "Dylan", "Johnny", "Phillip", "Victor", "Clarence", "Ernest", "Martin", "Craig", "Stanley", "Shawn", "Travis", "Bradley", "Leonard", "Earl", "Gabriel", "Jimmy", "Francis", "Todd", "Noah", "Danny", "Dale", "Cody", "Carlos", "Allen", "Frederick", "Logan", "Curtis", "Alex", "Joel", "Luis", "Norman", "Marvin", "Glenn", "Tony", "Nathaniel", "Rodney", "Melvin", "Alfred", "Steve", "Cameron", "Chad", "Edwin", "Caleb", "Evan", "Antonio", "Lee", "Herbert", "Jeffery", "Isaac", "Derek", "Ricky", "Marcus", "Theodore", "Elijah", "Luke", "Jesus", "Eddie", "Troy", "Mike", "Dustin", "Ray", "Adrian", "Bernard", "Leroy", "Angel", "Randall", "Wesley", "Ian", "Jared", "Mason", "Hunter", "Calvin", "Oscar", "Clifford", "Jay", "Shane", "Ronnie", "Barry", "Lucas", "Corey", "Manuel", "Leo", "Tommy", "Warren", "Jackson", "Isaiah", "Connor", "Don", "Dean", "Jon", "Julian", "Miguel", "Bill", "Lloyd", "Charlie", "Mitchell", "Leon", "Jerome", "Darrell", "Jeremiah", "Alvin", "Brett", "Seth", "Floyd", "Jim", "Blake", "Micheal", "Gordon", "Trevor", "Lewis", "Erik", "Edgar", "Vernon", "Devin", "Gavin", "Jayden", "Chris", "Clyde", "Tom", "Derrick", "Mario", "Brent", "Marc", "Herman", "Chase", "Dominic", "Ricardo", "Franklin", "Maurice", "Max", "Aiden", "Owen", "Lester", "Gilbert", "Elmer", "Gene", "Francisco", "Glen", "Cory", "Garrett", "Clayton", "Sam", "Jorge", "Chester", "Alejandro", "Jeff", "Harvey", "Milton", "Cole", "Ivan", "Andre", "Duane", "Landon"], + "female": ["Mary", "Emma", "Elizabeth", "Minnie", "Margaret", "Ida", "Alice", "Bertha", "Sarah", "Annie", "Clara", "Ella", "Florence", "Cora", "Martha", "Laura", "Nellie", "Grace", "Carrie", "Maude", "Mabel", "Bessie", "Jennie", "Gertrude", "Julia", "Hattie", "Edith", "Mattie", "Rose", "Catherine", "Lillian", "Ada", "Lillie", "Helen", "Jessie", "Louise", "Ethel", "Lula", "Myrtle", "Eva", "Frances", "Lena", "Lucy", "Edna", "Maggie", "Pearl", "Daisy", "Fannie", "Josephine", "Dora", "Rosa", "Katherine", "Agnes", "Marie", "Nora", "May", "Mamie", "Blanche", "Stella", "Ellen", "Nancy", "Effie", "Sallie", "Nettie", "Della", "Lizzie", "Flora", "Susie", "Maud", "Mae", "Etta", "Harriet", "Sadie", "Caroline", "Katie", "Lydia", "Elsie", "Kate", "Susan", "Mollie", "Alma", "Addie", "Georgia", "Eliza", "Lulu", "Nannie", "Lottie", "Amanda", "Belle", "Charlotte", "Rebecca", "Ruth", "Viola", "Olive", "Amelia", "Hannah", "Jane", "Virginia", "Emily", "Matilda", "Irene", "Kathryn", "Esther", "Willie", "Henrietta", "Ollie", "Amy", "Rachel", "Sara", "Estella", "Theresa", "Augusta", "Ora", "Pauline", "Josie", "Lola", "Sophia", "Leona", "Anne", "Mildred", "Ann", "Beulah", "Callie", "Lou", "Delia", "Eleanor", "Barbara", "Iva", "Louisa", "Maria", "Mayme", "Evelyn", "Estelle", "Nina", "Betty", "Marion", "Bettie", "Dorothy", "Luella", "Inez", "Lela", "Rosie", "Allie", "Millie", "Janie", "Cornelia", "Victoria", "Ruby", "Winifred", "Alta", "Celia", "Christine", "Beatrice", "Birdie", "Harriett", "Mable", "Myra", "Sophie", "Tillie", "Isabel", "Sylvia", "Carolyn", "Isabelle", "Leila", "Sally", "Ina", "Essie", "Bertie", "Nell", "Alberta", "Katharine", "Lora", "Rena", "Mina", "Rhoda", "Mathilda", "Abbie", "Eula", "Dollie", "Hettie", "Eunice", "Fanny", "Ola", "Lenora", "Adelaide", "Christina", "Lelia", "Nelle", "Sue", "Johanna", "Lilly", "Lucinda", "Minerva", "Lettie", "Roxie", "Cynthia", "Helena", "Hilda", "Hulda", "Bernice", "Genevieve", "Jean", "Cordelia", "Marian", "Francis", "Jeanette", "Adeline", "Gussie", "Leah", "Lois", "Lura", "Mittie", "Hallie", "Isabella", "Olga", "Phoebe", "Teresa", "Hester", "Lida", "Lina", "Winnie", "Claudia", "Marguerite", "Vera", "Cecelia", "Bess", "Emilie", "John", "Rosetta", "Verna", "Myrtie", "Cecilia", "Elva", "Olivia", "Ophelia", "Georgie", "Elnora", "Violet", "Adele", "Lily", "Linnie", "Loretta", "Madge", "Polly", "Virgie", "Eugenia", "Lucile", "Lucille", "Mabelle", "Rosalie"] + }, + + lastNames: ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Davis', 'Miller', 'Wilson', 'Moore', 'Taylor', 'Anderson', 'Thomas', 'Jackson', 'White', 'Harris', 'Martin', 'Thompson', 'Garcia', 'Martinez', 'Robinson', 'Clark', 'Rodriguez', 'Lewis', 'Lee', 'Walker', 'Hall', 'Allen', 'Young', 'Hernandez', 'King', 'Wright', 'Lopez', 'Hill', 'Scott', 'Green', 'Adams', 'Baker', 'Gonzalez', 'Nelson', 'Carter', 'Mitchell', 'Perez', 'Roberts', 'Turner', 'Phillips', 'Campbell', 'Parker', 'Evans', 'Edwards', 'Collins', 'Stewart', 'Sanchez', 'Morris', 'Rogers', 'Reed', 'Cook', 'Morgan', 'Bell', 'Murphy', 'Bailey', 'Rivera', 'Cooper', 'Richardson', 'Cox', 'Howard', 'Ward', 'Torres', 'Peterson', 'Gray', 'Ramirez', 'James', 'Watson', 'Brooks', 'Kelly', 'Sanders', 'Price', 'Bennett', 'Wood', 'Barnes', 'Ross', 'Henderson', 'Coleman', 'Jenkins', 'Perry', 'Powell', 'Long', 'Patterson', 'Hughes', 'Flores', 'Washington', 'Butler', 'Simmons', 'Foster', 'Gonzales', 'Bryant', 'Alexander', 'Russell', 'Griffin', 'Diaz', 'Hayes', 'Myers', 'Ford', 'Hamilton', 'Graham', 'Sullivan', 'Wallace', 'Woods', 'Cole', 'West', 'Jordan', 'Owens', 'Reynolds', 'Fisher', 'Ellis', 'Harrison', 'Gibson', 'McDonald', 'Cruz', 'Marshall', 'Ortiz', 'Gomez', 'Murray', 'Freeman', 'Wells', 'Webb', 'Simpson', 'Stevens', 'Tucker', 'Porter', 'Hunter', 'Hicks', 'Crawford', 'Henry', 'Boyd', 'Mason', 'Morales', 'Kennedy', 'Warren', 'Dixon', 'Ramos', 'Reyes', 'Burns', 'Gordon', 'Shaw', 'Holmes', 'Rice', 'Robertson', 'Hunt', 'Black', 'Daniels', 'Palmer', 'Mills', 'Nichols', 'Grant', 'Knight', 'Ferguson', 'Rose', 'Stone', 'Hawkins', 'Dunn', 'Perkins', 'Hudson', 'Spencer', 'Gardner', 'Stephens', 'Payne', 'Pierce', 'Berry', 'Matthews', 'Arnold', 'Wagner', 'Willis', 'Ray', 'Watkins', 'Olson', 'Carroll', 'Duncan', 'Snyder', 'Hart', 'Cunningham', 'Bradley', 'Lane', 'Andrews', 'Ruiz', 'Harper', 'Fox', 'Riley', 'Armstrong', 'Carpenter', 'Weaver', 'Greene', 'Lawrence', 'Elliott', 'Chavez', 'Sims', 'Austin', 'Peters', 'Kelley', 'Franklin', 'Lawson', 'Fields', 'Gutierrez', 'Ryan', 'Schmidt', 'Carr', 'Vasquez', 'Castillo', 'Wheeler', 'Chapman', 'Oliver', 'Montgomery', 'Richards', 'Williamson', 'Johnston', 'Banks', 'Meyer', 'Bishop', 'McCoy', 'Howell', 'Alvarez', 'Morrison', 'Hansen', 'Fernandez', 'Garza', 'Harvey', 'Little', 'Burton', 'Stanley', 'Nguyen', 'George', 'Jacobs', 'Reid', 'Kim', 'Fuller', 'Lynch', 'Dean', 'Gilbert', 'Garrett', 'Romero', 'Welch', 'Larson', 'Frazier', 'Burke', 'Hanson', 'Day', 'Mendoza', 'Moreno', 'Bowman', 'Medina', 'Fowler', 'Brewer', 'Hoffman', 'Carlson', 'Silva', 'Pearson', 'Holland', 'Douglas', 'Fleming', 'Jensen', 'Vargas', 'Byrd', 'Davidson', 'Hopkins', 'May', 'Terry', 'Herrera', 'Wade', 'Soto', 'Walters', 'Curtis', 'Neal', 'Caldwell', 'Lowe', 'Jennings', 'Barnett', 'Graves', 'Jimenez', 'Horton', 'Shelton', 'Barrett', 'Obrien', 'Castro', 'Sutton', 'Gregory', 'McKinney', 'Lucas', 'Miles', 'Craig', 'Rodriquez', 'Chambers', 'Holt', 'Lambert', 'Fletcher', 'Watts', 'Bates', 'Hale', 'Rhodes', 'Pena', 'Beck', 'Newman', 'Haynes', 'McDaniel', 'Mendez', 'Bush', 'Vaughn', 'Parks', 'Dawson', 'Santiago', 'Norris', 'Hardy', 'Love', 'Steele', 'Curry', 'Powers', 'Schultz', 'Barker', 'Guzman', 'Page', 'Munoz', 'Ball', 'Keller', 'Chandler', 'Weber', 'Leonard', 'Walsh', 'Lyons', 'Ramsey', 'Wolfe', 'Schneider', 'Mullins', 'Benson', 'Sharp', 'Bowen', 'Daniel', 'Barber', 'Cummings', 'Hines', 'Baldwin', 'Griffith', 'Valdez', 'Hubbard', 'Salazar', 'Reeves', 'Warner', 'Stevenson', 'Burgess', 'Santos', 'Tate', 'Cross', 'Garner', 'Mann', 'Mack', 'Moss', 'Thornton', 'Dennis', 'McGee', 'Farmer', 'Delgado', 'Aguilar', 'Vega', 'Glover', 'Manning', 'Cohen', 'Harmon', 'Rodgers', 'Robbins', 'Newton', 'Todd', 'Blair', 'Higgins', 'Ingram', 'Reese', 'Cannon', 'Strickland', 'Townsend', 'Potter', 'Goodwin', 'Walton', 'Rowe', 'Hampton', 'Ortega', 'Patton', 'Swanson', 'Joseph', 'Francis', 'Goodman', 'Maldonado', 'Yates', 'Becker', 'Erickson', 'Hodges', 'Rios', 'Conner', 'Adkins', 'Webster', 'Norman', 'Malone', 'Hammond', 'Flowers', 'Cobb', 'Moody', 'Quinn', 'Blake', 'Maxwell', 'Pope', 'Floyd', 'Osborne', 'Paul', 'McCarthy', 'Guerrero', 'Lindsey', 'Estrada', 'Sandoval', 'Gibbs', 'Tyler', 'Gross', 'Fitzgerald', 'Stokes', 'Doyle', 'Sherman', 'Saunders', 'Wise', 'Colon', 'Gill', 'Alvarado', 'Greer', 'Padilla', 'Simon', 'Waters', 'Nunez', 'Ballard', 'Schwartz', 'McBride', 'Houston', 'Christensen', 'Klein', 'Pratt', 'Briggs', 'Parsons', 'McLaughlin', 'Zimmerman', 'French', 'Buchanan', 'Moran', 'Copeland', 'Roy', 'Pittman', 'Brady', 'McCormick', 'Holloway', 'Brock', 'Poole', 'Frank', 'Logan', 'Owen', 'Bass', 'Marsh', 'Drake', 'Wong', 'Jefferson', 'Park', 'Morton', 'Abbott', 'Sparks', 'Patrick', 'Norton', 'Huff', 'Clayton', 'Massey', 'Lloyd', 'Figueroa', 'Carson', 'Bowers', 'Roberson', 'Barton', 'Tran', 'Lamb', 'Harrington', 'Casey', 'Boone', 'Cortez', 'Clarke', 'Mathis', 'Singleton', 'Wilkins', 'Cain', 'Bryan', 'Underwood', 'Hogan', 'McKenzie', 'Collier', 'Luna', 'Phelps', 'McGuire', 'Allison', 'Bridges', 'Wilkerson', 'Nash', 'Summers', 'Atkins'], + + // Data taken from https://github.com/umpirsky/country-list/blob/master/country/cldr/en_US/country.json + countries: [{"name":"Afghanistan","abbreviation":"AF"},{"name":"Albania","abbreviation":"AL"},{"name":"Algeria","abbreviation":"DZ"},{"name":"American Samoa","abbreviation":"AS"},{"name":"Andorra","abbreviation":"AD"},{"name":"Angola","abbreviation":"AO"},{"name":"Anguilla","abbreviation":"AI"},{"name":"Antarctica","abbreviation":"AQ"},{"name":"Antigua and Barbuda","abbreviation":"AG"},{"name":"Argentina","abbreviation":"AR"},{"name":"Armenia","abbreviation":"AM"},{"name":"Aruba","abbreviation":"AW"},{"name":"Australia","abbreviation":"AU"},{"name":"Austria","abbreviation":"AT"},{"name":"Azerbaijan","abbreviation":"AZ"},{"name":"Bahamas","abbreviation":"BS"},{"name":"Bahrain","abbreviation":"BH"},{"name":"Bangladesh","abbreviation":"BD"},{"name":"Barbados","abbreviation":"BB"},{"name":"Belarus","abbreviation":"BY"},{"name":"Belgium","abbreviation":"BE"},{"name":"Belize","abbreviation":"BZ"},{"name":"Benin","abbreviation":"BJ"},{"name":"Bermuda","abbreviation":"BM"},{"name":"Bhutan","abbreviation":"BT"},{"name":"Bolivia","abbreviation":"BO"},{"name":"Bosnia and Herzegovina","abbreviation":"BA"},{"name":"Botswana","abbreviation":"BW"},{"name":"Bouvet Island","abbreviation":"BV"},{"name":"Brazil","abbreviation":"BR"},{"name":"British Antarctic Territory","abbreviation":"BQ"},{"name":"British Indian Ocean Territory","abbreviation":"IO"},{"name":"British Virgin Islands","abbreviation":"VG"},{"name":"Brunei","abbreviation":"BN"},{"name":"Bulgaria","abbreviation":"BG"},{"name":"Burkina Faso","abbreviation":"BF"},{"name":"Burundi","abbreviation":"BI"},{"name":"Cambodia","abbreviation":"KH"},{"name":"Cameroon","abbreviation":"CM"},{"name":"Canada","abbreviation":"CA"},{"name":"Canton and Enderbury Islands","abbreviation":"CT"},{"name":"Cape Verde","abbreviation":"CV"},{"name":"Cayman Islands","abbreviation":"KY"},{"name":"Central African Republic","abbreviation":"CF"},{"name":"Chad","abbreviation":"TD"},{"name":"Chile","abbreviation":"CL"},{"name":"China","abbreviation":"CN"},{"name":"Christmas Island","abbreviation":"CX"},{"name":"Cocos [Keeling] Islands","abbreviation":"CC"},{"name":"Colombia","abbreviation":"CO"},{"name":"Comoros","abbreviation":"KM"},{"name":"Congo - Brazzaville","abbreviation":"CG"},{"name":"Congo - Kinshasa","abbreviation":"CD"},{"name":"Cook Islands","abbreviation":"CK"},{"name":"Costa Rica","abbreviation":"CR"},{"name":"Croatia","abbreviation":"HR"},{"name":"Cuba","abbreviation":"CU"},{"name":"Cyprus","abbreviation":"CY"},{"name":"Czech Republic","abbreviation":"CZ"},{"name":"Côte d’Ivoire","abbreviation":"CI"},{"name":"Denmark","abbreviation":"DK"},{"name":"Djibouti","abbreviation":"DJ"},{"name":"Dominica","abbreviation":"DM"},{"name":"Dominican Republic","abbreviation":"DO"},{"name":"Dronning Maud Land","abbreviation":"NQ"},{"name":"East Germany","abbreviation":"DD"},{"name":"Ecuador","abbreviation":"EC"},{"name":"Egypt","abbreviation":"EG"},{"name":"El Salvador","abbreviation":"SV"},{"name":"Equatorial Guinea","abbreviation":"GQ"},{"name":"Eritrea","abbreviation":"ER"},{"name":"Estonia","abbreviation":"EE"},{"name":"Ethiopia","abbreviation":"ET"},{"name":"Falkland Islands","abbreviation":"FK"},{"name":"Faroe Islands","abbreviation":"FO"},{"name":"Fiji","abbreviation":"FJ"},{"name":"Finland","abbreviation":"FI"},{"name":"France","abbreviation":"FR"},{"name":"French Guiana","abbreviation":"GF"},{"name":"French Polynesia","abbreviation":"PF"},{"name":"French Southern Territories","abbreviation":"TF"},{"name":"French Southern and Antarctic Territories","abbreviation":"FQ"},{"name":"Gabon","abbreviation":"GA"},{"name":"Gambia","abbreviation":"GM"},{"name":"Georgia","abbreviation":"GE"},{"name":"Germany","abbreviation":"DE"},{"name":"Ghana","abbreviation":"GH"},{"name":"Gibraltar","abbreviation":"GI"},{"name":"Greece","abbreviation":"GR"},{"name":"Greenland","abbreviation":"GL"},{"name":"Grenada","abbreviation":"GD"},{"name":"Guadeloupe","abbreviation":"GP"},{"name":"Guam","abbreviation":"GU"},{"name":"Guatemala","abbreviation":"GT"},{"name":"Guernsey","abbreviation":"GG"},{"name":"Guinea","abbreviation":"GN"},{"name":"Guinea-Bissau","abbreviation":"GW"},{"name":"Guyana","abbreviation":"GY"},{"name":"Haiti","abbreviation":"HT"},{"name":"Heard Island and McDonald Islands","abbreviation":"HM"},{"name":"Honduras","abbreviation":"HN"},{"name":"Hong Kong SAR China","abbreviation":"HK"},{"name":"Hungary","abbreviation":"HU"},{"name":"Iceland","abbreviation":"IS"},{"name":"India","abbreviation":"IN"},{"name":"Indonesia","abbreviation":"ID"},{"name":"Iran","abbreviation":"IR"},{"name":"Iraq","abbreviation":"IQ"},{"name":"Ireland","abbreviation":"IE"},{"name":"Isle of Man","abbreviation":"IM"},{"name":"Israel","abbreviation":"IL"},{"name":"Italy","abbreviation":"IT"},{"name":"Jamaica","abbreviation":"JM"},{"name":"Japan","abbreviation":"JP"},{"name":"Jersey","abbreviation":"JE"},{"name":"Johnston Island","abbreviation":"JT"},{"name":"Jordan","abbreviation":"JO"},{"name":"Kazakhstan","abbreviation":"KZ"},{"name":"Kenya","abbreviation":"KE"},{"name":"Kiribati","abbreviation":"KI"},{"name":"Kuwait","abbreviation":"KW"},{"name":"Kyrgyzstan","abbreviation":"KG"},{"name":"Laos","abbreviation":"LA"},{"name":"Latvia","abbreviation":"LV"},{"name":"Lebanon","abbreviation":"LB"},{"name":"Lesotho","abbreviation":"LS"},{"name":"Liberia","abbreviation":"LR"},{"name":"Libya","abbreviation":"LY"},{"name":"Liechtenstein","abbreviation":"LI"},{"name":"Lithuania","abbreviation":"LT"},{"name":"Luxembourg","abbreviation":"LU"},{"name":"Macau SAR China","abbreviation":"MO"},{"name":"Macedonia","abbreviation":"MK"},{"name":"Madagascar","abbreviation":"MG"},{"name":"Malawi","abbreviation":"MW"},{"name":"Malaysia","abbreviation":"MY"},{"name":"Maldives","abbreviation":"MV"},{"name":"Mali","abbreviation":"ML"},{"name":"Malta","abbreviation":"MT"},{"name":"Marshall Islands","abbreviation":"MH"},{"name":"Martinique","abbreviation":"MQ"},{"name":"Mauritania","abbreviation":"MR"},{"name":"Mauritius","abbreviation":"MU"},{"name":"Mayotte","abbreviation":"YT"},{"name":"Metropolitan France","abbreviation":"FX"},{"name":"Mexico","abbreviation":"MX"},{"name":"Micronesia","abbreviation":"FM"},{"name":"Midway Islands","abbreviation":"MI"},{"name":"Moldova","abbreviation":"MD"},{"name":"Monaco","abbreviation":"MC"},{"name":"Mongolia","abbreviation":"MN"},{"name":"Montenegro","abbreviation":"ME"},{"name":"Montserrat","abbreviation":"MS"},{"name":"Morocco","abbreviation":"MA"},{"name":"Mozambique","abbreviation":"MZ"},{"name":"Myanmar [Burma]","abbreviation":"MM"},{"name":"Namibia","abbreviation":"NA"},{"name":"Nauru","abbreviation":"NR"},{"name":"Nepal","abbreviation":"NP"},{"name":"Netherlands","abbreviation":"NL"},{"name":"Netherlands Antilles","abbreviation":"AN"},{"name":"Neutral Zone","abbreviation":"NT"},{"name":"New Caledonia","abbreviation":"NC"},{"name":"New Zealand","abbreviation":"NZ"},{"name":"Nicaragua","abbreviation":"NI"},{"name":"Niger","abbreviation":"NE"},{"name":"Nigeria","abbreviation":"NG"},{"name":"Niue","abbreviation":"NU"},{"name":"Norfolk Island","abbreviation":"NF"},{"name":"North Korea","abbreviation":"KP"},{"name":"North Vietnam","abbreviation":"VD"},{"name":"Northern Mariana Islands","abbreviation":"MP"},{"name":"Norway","abbreviation":"NO"},{"name":"Oman","abbreviation":"OM"},{"name":"Pacific Islands Trust Territory","abbreviation":"PC"},{"name":"Pakistan","abbreviation":"PK"},{"name":"Palau","abbreviation":"PW"},{"name":"Palestinian Territories","abbreviation":"PS"},{"name":"Panama","abbreviation":"PA"},{"name":"Panama Canal Zone","abbreviation":"PZ"},{"name":"Papua New Guinea","abbreviation":"PG"},{"name":"Paraguay","abbreviation":"PY"},{"name":"People's Democratic Republic of Yemen","abbreviation":"YD"},{"name":"Peru","abbreviation":"PE"},{"name":"Philippines","abbreviation":"PH"},{"name":"Pitcairn Islands","abbreviation":"PN"},{"name":"Poland","abbreviation":"PL"},{"name":"Portugal","abbreviation":"PT"},{"name":"Puerto Rico","abbreviation":"PR"},{"name":"Qatar","abbreviation":"QA"},{"name":"Romania","abbreviation":"RO"},{"name":"Russia","abbreviation":"RU"},{"name":"Rwanda","abbreviation":"RW"},{"name":"Réunion","abbreviation":"RE"},{"name":"Saint Barthélemy","abbreviation":"BL"},{"name":"Saint Helena","abbreviation":"SH"},{"name":"Saint Kitts and Nevis","abbreviation":"KN"},{"name":"Saint Lucia","abbreviation":"LC"},{"name":"Saint Martin","abbreviation":"MF"},{"name":"Saint Pierre and Miquelon","abbreviation":"PM"},{"name":"Saint Vincent and the Grenadines","abbreviation":"VC"},{"name":"Samoa","abbreviation":"WS"},{"name":"San Marino","abbreviation":"SM"},{"name":"Saudi Arabia","abbreviation":"SA"},{"name":"Senegal","abbreviation":"SN"},{"name":"Serbia","abbreviation":"RS"},{"name":"Serbia and Montenegro","abbreviation":"CS"},{"name":"Seychelles","abbreviation":"SC"},{"name":"Sierra Leone","abbreviation":"SL"},{"name":"Singapore","abbreviation":"SG"},{"name":"Slovakia","abbreviation":"SK"},{"name":"Slovenia","abbreviation":"SI"},{"name":"Solomon Islands","abbreviation":"SB"},{"name":"Somalia","abbreviation":"SO"},{"name":"South Africa","abbreviation":"ZA"},{"name":"South Georgia and the South Sandwich Islands","abbreviation":"GS"},{"name":"South Korea","abbreviation":"KR"},{"name":"Spain","abbreviation":"ES"},{"name":"Sri Lanka","abbreviation":"LK"},{"name":"Sudan","abbreviation":"SD"},{"name":"Suriname","abbreviation":"SR"},{"name":"Svalbard and Jan Mayen","abbreviation":"SJ"},{"name":"Swaziland","abbreviation":"SZ"},{"name":"Sweden","abbreviation":"SE"},{"name":"Switzerland","abbreviation":"CH"},{"name":"Syria","abbreviation":"SY"},{"name":"São Tomé and Príncipe","abbreviation":"ST"},{"name":"Taiwan","abbreviation":"TW"},{"name":"Tajikistan","abbreviation":"TJ"},{"name":"Tanzania","abbreviation":"TZ"},{"name":"Thailand","abbreviation":"TH"},{"name":"Timor-Leste","abbreviation":"TL"},{"name":"Togo","abbreviation":"TG"},{"name":"Tokelau","abbreviation":"TK"},{"name":"Tonga","abbreviation":"TO"},{"name":"Trinidad and Tobago","abbreviation":"TT"},{"name":"Tunisia","abbreviation":"TN"},{"name":"Turkey","abbreviation":"TR"},{"name":"Turkmenistan","abbreviation":"TM"},{"name":"Turks and Caicos Islands","abbreviation":"TC"},{"name":"Tuvalu","abbreviation":"TV"},{"name":"U.S. Minor Outlying Islands","abbreviation":"UM"},{"name":"U.S. Miscellaneous Pacific Islands","abbreviation":"PU"},{"name":"U.S. Virgin Islands","abbreviation":"VI"},{"name":"Uganda","abbreviation":"UG"},{"name":"Ukraine","abbreviation":"UA"},{"name":"Union of Soviet Socialist Republics","abbreviation":"SU"},{"name":"United Arab Emirates","abbreviation":"AE"},{"name":"United Kingdom","abbreviation":"GB"},{"name":"United States","abbreviation":"US"},{"name":"Unknown or Invalid Region","abbreviation":"ZZ"},{"name":"Uruguay","abbreviation":"UY"},{"name":"Uzbekistan","abbreviation":"UZ"},{"name":"Vanuatu","abbreviation":"VU"},{"name":"Vatican City","abbreviation":"VA"},{"name":"Venezuela","abbreviation":"VE"},{"name":"Vietnam","abbreviation":"VN"},{"name":"Wake Island","abbreviation":"WK"},{"name":"Wallis and Futuna","abbreviation":"WF"},{"name":"Western Sahara","abbreviation":"EH"},{"name":"Yemen","abbreviation":"YE"},{"name":"Zambia","abbreviation":"ZM"},{"name":"Zimbabwe","abbreviation":"ZW"},{"name":"Åland Islands","abbreviation":"AX"}], + + provinces: [ + {name: 'Alberta', abbreviation: 'AB'}, + {name: 'British Columbia', abbreviation: 'BC'}, + {name: 'Manitoba', abbreviation: 'MB'}, + {name: 'New Brunswick', abbreviation: 'NB'}, + {name: 'Newfoundland and Labrador', abbreviation: 'NL'}, + {name: 'Nova Scotia', abbreviation: 'NS'}, + {name: 'Ontario', abbreviation: 'ON'}, + {name: 'Prince Edward Island', abbreviation: 'PE'}, + {name: 'Quebec', abbreviation: 'QC'}, + {name: 'Saskatchewan', abbreviation: 'SK'}, + + // The case could be made that the following are not actually provinces + // since they are technically considered "territories" however they all + // look the same on an envelope! + {name: 'Northwest Territories', abbreviation: 'NT'}, + {name: 'Nunavut', abbreviation: 'NU'}, + {name: 'Yukon', abbreviation: 'YT'} + ], + + us_states_and_dc: [ + {name: 'Alabama', abbreviation: 'AL'}, + {name: 'Alaska', abbreviation: 'AK'}, + {name: 'Arizona', abbreviation: 'AZ'}, + {name: 'Arkansas', abbreviation: 'AR'}, + {name: 'California', abbreviation: 'CA'}, + {name: 'Colorado', abbreviation: 'CO'}, + {name: 'Connecticut', abbreviation: 'CT'}, + {name: 'Delaware', abbreviation: 'DE'}, + {name: 'District of Columbia', abbreviation: 'DC'}, + {name: 'Florida', abbreviation: 'FL'}, + {name: 'Georgia', abbreviation: 'GA'}, + {name: 'Hawaii', abbreviation: 'HI'}, + {name: 'Idaho', abbreviation: 'ID'}, + {name: 'Illinois', abbreviation: 'IL'}, + {name: 'Indiana', abbreviation: 'IN'}, + {name: 'Iowa', abbreviation: 'IA'}, + {name: 'Kansas', abbreviation: 'KS'}, + {name: 'Kentucky', abbreviation: 'KY'}, + {name: 'Louisiana', abbreviation: 'LA'}, + {name: 'Maine', abbreviation: 'ME'}, + {name: 'Maryland', abbreviation: 'MD'}, + {name: 'Massachusetts', abbreviation: 'MA'}, + {name: 'Michigan', abbreviation: 'MI'}, + {name: 'Minnesota', abbreviation: 'MN'}, + {name: 'Mississippi', abbreviation: 'MS'}, + {name: 'Missouri', abbreviation: 'MO'}, + {name: 'Montana', abbreviation: 'MT'}, + {name: 'Nebraska', abbreviation: 'NE'}, + {name: 'Nevada', abbreviation: 'NV'}, + {name: 'New Hampshire', abbreviation: 'NH'}, + {name: 'New Jersey', abbreviation: 'NJ'}, + {name: 'New Mexico', abbreviation: 'NM'}, + {name: 'New York', abbreviation: 'NY'}, + {name: 'North Carolina', abbreviation: 'NC'}, + {name: 'North Dakota', abbreviation: 'ND'}, + {name: 'Ohio', abbreviation: 'OH'}, + {name: 'Oklahoma', abbreviation: 'OK'}, + {name: 'Oregon', abbreviation: 'OR'}, + {name: 'Pennsylvania', abbreviation: 'PA'}, + {name: 'Rhode Island', abbreviation: 'RI'}, + {name: 'South Carolina', abbreviation: 'SC'}, + {name: 'South Dakota', abbreviation: 'SD'}, + {name: 'Tennessee', abbreviation: 'TN'}, + {name: 'Texas', abbreviation: 'TX'}, + {name: 'Utah', abbreviation: 'UT'}, + {name: 'Vermont', abbreviation: 'VT'}, + {name: 'Virginia', abbreviation: 'VA'}, + {name: 'Washington', abbreviation: 'WA'}, + {name: 'West Virginia', abbreviation: 'WV'}, + {name: 'Wisconsin', abbreviation: 'WI'}, + {name: 'Wyoming', abbreviation: 'WY'} + ], + + territories: [ + {name: 'American Samoa', abbreviation: 'AS'}, + {name: 'Federated States of Micronesia', abbreviation: 'FM'}, + {name: 'Guam', abbreviation: 'GU'}, + {name: 'Marshall Islands', abbreviation: 'MH'}, + {name: 'Northern Mariana Islands', abbreviation: 'MP'}, + {name: 'Puerto Rico', abbreviation: 'PR'}, + {name: 'Virgin Islands, U.S.', abbreviation: 'VI'} + ], + + armed_forces: [ + {name: 'Armed Forces Europe', abbreviation: 'AE'}, + {name: 'Armed Forces Pacific', abbreviation: 'AP'}, + {name: 'Armed Forces the Americas', abbreviation: 'AA'} + ], + + street_suffixes: [ + {name: 'Avenue', abbreviation: 'Ave'}, + {name: 'Boulevard', abbreviation: 'Blvd'}, + {name: 'Center', abbreviation: 'Ctr'}, + {name: 'Circle', abbreviation: 'Cir'}, + {name: 'Court', abbreviation: 'Ct'}, + {name: 'Drive', abbreviation: 'Dr'}, + {name: 'Extension', abbreviation: 'Ext'}, + {name: 'Glen', abbreviation: 'Gln'}, + {name: 'Grove', abbreviation: 'Grv'}, + {name: 'Heights', abbreviation: 'Hts'}, + {name: 'Highway', abbreviation: 'Hwy'}, + {name: 'Junction', abbreviation: 'Jct'}, + {name: 'Key', abbreviation: 'Key'}, + {name: 'Lane', abbreviation: 'Ln'}, + {name: 'Loop', abbreviation: 'Loop'}, + {name: 'Manor', abbreviation: 'Mnr'}, + {name: 'Mill', abbreviation: 'Mill'}, + {name: 'Park', abbreviation: 'Park'}, + {name: 'Parkway', abbreviation: 'Pkwy'}, + {name: 'Pass', abbreviation: 'Pass'}, + {name: 'Path', abbreviation: 'Path'}, + {name: 'Pike', abbreviation: 'Pike'}, + {name: 'Place', abbreviation: 'Pl'}, + {name: 'Plaza', abbreviation: 'Plz'}, + {name: 'Point', abbreviation: 'Pt'}, + {name: 'Ridge', abbreviation: 'Rdg'}, + {name: 'River', abbreviation: 'Riv'}, + {name: 'Road', abbreviation: 'Rd'}, + {name: 'Square', abbreviation: 'Sq'}, + {name: 'Street', abbreviation: 'St'}, + {name: 'Terrace', abbreviation: 'Ter'}, + {name: 'Trail', abbreviation: 'Trl'}, + {name: 'Turnpike', abbreviation: 'Tpke'}, + {name: 'View', abbreviation: 'Vw'}, + {name: 'Way', abbreviation: 'Way'} + ], + + months: [ + {name: 'January', short_name: 'Jan', numeric: '01', days: 31}, + // Not messing with leap years... + {name: 'February', short_name: 'Feb', numeric: '02', days: 28}, + {name: 'March', short_name: 'Mar', numeric: '03', days: 31}, + {name: 'April', short_name: 'Apr', numeric: '04', days: 30}, + {name: 'May', short_name: 'May', numeric: '05', days: 31}, + {name: 'June', short_name: 'Jun', numeric: '06', days: 30}, + {name: 'July', short_name: 'Jul', numeric: '07', days: 31}, + {name: 'August', short_name: 'Aug', numeric: '08', days: 31}, + {name: 'September', short_name: 'Sep', numeric: '09', days: 30}, + {name: 'October', short_name: 'Oct', numeric: '10', days: 31}, + {name: 'November', short_name: 'Nov', numeric: '11', days: 30}, + {name: 'December', short_name: 'Dec', numeric: '12', days: 31} + ], + + // http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29 + cc_types: [ + {name: "American Express", short_name: 'amex', prefix: '34', length: 15}, + {name: "Bankcard", short_name: 'bankcard', prefix: '5610', length: 16}, + {name: "China UnionPay", short_name: 'chinaunion', prefix: '62', length: 16}, + {name: "Diners Club Carte Blanche", short_name: 'dccarte', prefix: '300', length: 14}, + {name: "Diners Club enRoute", short_name: 'dcenroute', prefix: '2014', length: 15}, + {name: "Diners Club International", short_name: 'dcintl', prefix: '36', length: 14}, + {name: "Diners Club United States & Canada", short_name: 'dcusc', prefix: '54', length: 16}, + {name: "Discover Card", short_name: 'discover', prefix: '6011', length: 16}, + {name: "InstaPayment", short_name: 'instapay', prefix: '637', length: 16}, + {name: "JCB", short_name: 'jcb', prefix: '3528', length: 16}, + {name: "Laser", short_name: 'laser', prefix: '6304', length: 16}, + {name: "Maestro", short_name: 'maestro', prefix: '5018', length: 16}, + {name: "Mastercard", short_name: 'mc', prefix: '51', length: 16}, + {name: "Solo", short_name: 'solo', prefix: '6334', length: 16}, + {name: "Switch", short_name: 'switch', prefix: '4903', length: 16}, + {name: "Visa", short_name: 'visa', prefix: '4', length: 16}, + {name: "Visa Electron", short_name: 'electron', prefix: '4026', length: 16} + ], + + //return all world currency by ISO 4217 + currency_types: [ + {'code' : 'AED', 'name' : 'United Arab Emirates Dirham'}, + {'code' : 'AFN', 'name' : 'Afghanistan Afghani'}, + {'code' : 'ALL', 'name' : 'Albania Lek'}, + {'code' : 'AMD', 'name' : 'Armenia Dram'}, + {'code' : 'ANG', 'name' : 'Netherlands Antilles Guilder'}, + {'code' : 'AOA', 'name' : 'Angola Kwanza'}, + {'code' : 'ARS', 'name' : 'Argentina Peso'}, + {'code' : 'AUD', 'name' : 'Australia Dollar'}, + {'code' : 'AWG', 'name' : 'Aruba Guilder'}, + {'code' : 'AZN', 'name' : 'Azerbaijan New Manat'}, + {'code' : 'BAM', 'name' : 'Bosnia and Herzegovina Convertible Marka'}, + {'code' : 'BBD', 'name' : 'Barbados Dollar'}, + {'code' : 'BDT', 'name' : 'Bangladesh Taka'}, + {'code' : 'BGN', 'name' : 'Bulgaria Lev'}, + {'code' : 'BHD', 'name' : 'Bahrain Dinar'}, + {'code' : 'BIF', 'name' : 'Burundi Franc'}, + {'code' : 'BMD', 'name' : 'Bermuda Dollar'}, + {'code' : 'BND', 'name' : 'Brunei Darussalam Dollar'}, + {'code' : 'BOB', 'name' : 'Bolivia Boliviano'}, + {'code' : 'BRL', 'name' : 'Brazil Real'}, + {'code' : 'BSD', 'name' : 'Bahamas Dollar'}, + {'code' : 'BTN', 'name' : 'Bhutan Ngultrum'}, + {'code' : 'BWP', 'name' : 'Botswana Pula'}, + {'code' : 'BYR', 'name' : 'Belarus Ruble'}, + {'code' : 'BZD', 'name' : 'Belize Dollar'}, + {'code' : 'CAD', 'name' : 'Canada Dollar'}, + {'code' : 'CDF', 'name' : 'Congo/Kinshasa Franc'}, + {'code' : 'CHF', 'name' : 'Switzerland Franc'}, + {'code' : 'CLP', 'name' : 'Chile Peso'}, + {'code' : 'CNY', 'name' : 'China Yuan Renminbi'}, + {'code' : 'COP', 'name' : 'Colombia Peso'}, + {'code' : 'CRC', 'name' : 'Costa Rica Colon'}, + {'code' : 'CUC', 'name' : 'Cuba Convertible Peso'}, + {'code' : 'CUP', 'name' : 'Cuba Peso'}, + {'code' : 'CVE', 'name' : 'Cape Verde Escudo'}, + {'code' : 'CZK', 'name' : 'Czech Republic Koruna'}, + {'code' : 'DJF', 'name' : 'Djibouti Franc'}, + {'code' : 'DKK', 'name' : 'Denmark Krone'}, + {'code' : 'DOP', 'name' : 'Dominican Republic Peso'}, + {'code' : 'DZD', 'name' : 'Algeria Dinar'}, + {'code' : 'EGP', 'name' : 'Egypt Pound'}, + {'code' : 'ERN', 'name' : 'Eritrea Nakfa'}, + {'code' : 'ETB', 'name' : 'Ethiopia Birr'}, + {'code' : 'EUR', 'name' : 'Euro Member Countries'}, + {'code' : 'FJD', 'name' : 'Fiji Dollar'}, + {'code' : 'FKP', 'name' : 'Falkland Islands (Malvinas) Pound'}, + {'code' : 'GBP', 'name' : 'United Kingdom Pound'}, + {'code' : 'GEL', 'name' : 'Georgia Lari'}, + {'code' : 'GGP', 'name' : 'Guernsey Pound'}, + {'code' : 'GHS', 'name' : 'Ghana Cedi'}, + {'code' : 'GIP', 'name' : 'Gibraltar Pound'}, + {'code' : 'GMD', 'name' : 'Gambia Dalasi'}, + {'code' : 'GNF', 'name' : 'Guinea Franc'}, + {'code' : 'GTQ', 'name' : 'Guatemala Quetzal'}, + {'code' : 'GYD', 'name' : 'Guyana Dollar'}, + {'code' : 'HKD', 'name' : 'Hong Kong Dollar'}, + {'code' : 'HNL', 'name' : 'Honduras Lempira'}, + {'code' : 'HRK', 'name' : 'Croatia Kuna'}, + {'code' : 'HTG', 'name' : 'Haiti Gourde'}, + {'code' : 'HUF', 'name' : 'Hungary Forint'}, + {'code' : 'IDR', 'name' : 'Indonesia Rupiah'}, + {'code' : 'ILS', 'name' : 'Israel Shekel'}, + {'code' : 'IMP', 'name' : 'Isle of Man Pound'}, + {'code' : 'INR', 'name' : 'India Rupee'}, + {'code' : 'IQD', 'name' : 'Iraq Dinar'}, + {'code' : 'IRR', 'name' : 'Iran Rial'}, + {'code' : 'ISK', 'name' : 'Iceland Krona'}, + {'code' : 'JEP', 'name' : 'Jersey Pound'}, + {'code' : 'JMD', 'name' : 'Jamaica Dollar'}, + {'code' : 'JOD', 'name' : 'Jordan Dinar'}, + {'code' : 'JPY', 'name' : 'Japan Yen'}, + {'code' : 'KES', 'name' : 'Kenya Shilling'}, + {'code' : 'KGS', 'name' : 'Kyrgyzstan Som'}, + {'code' : 'KHR', 'name' : 'Cambodia Riel'}, + {'code' : 'KMF', 'name' : 'Comoros Franc'}, + {'code' : 'KPW', 'name' : 'Korea (North) Won'}, + {'code' : 'KRW', 'name' : 'Korea (South) Won'}, + {'code' : 'KWD', 'name' : 'Kuwait Dinar'}, + {'code' : 'KYD', 'name' : 'Cayman Islands Dollar'}, + {'code' : 'KZT', 'name' : 'Kazakhstan Tenge'}, + {'code' : 'LAK', 'name' : 'Laos Kip'}, + {'code' : 'LBP', 'name' : 'Lebanon Pound'}, + {'code' : 'LKR', 'name' : 'Sri Lanka Rupee'}, + {'code' : 'LRD', 'name' : 'Liberia Dollar'}, + {'code' : 'LSL', 'name' : 'Lesotho Loti'}, + {'code' : 'LTL', 'name' : 'Lithuania Litas'}, + {'code' : 'LYD', 'name' : 'Libya Dinar'}, + {'code' : 'MAD', 'name' : 'Morocco Dirham'}, + {'code' : 'MDL', 'name' : 'Moldova Leu'}, + {'code' : 'MGA', 'name' : 'Madagascar Ariary'}, + {'code' : 'MKD', 'name' : 'Macedonia Denar'}, + {'code' : 'MMK', 'name' : 'Myanmar (Burma) Kyat'}, + {'code' : 'MNT', 'name' : 'Mongolia Tughrik'}, + {'code' : 'MOP', 'name' : 'Macau Pataca'}, + {'code' : 'MRO', 'name' : 'Mauritania Ouguiya'}, + {'code' : 'MUR', 'name' : 'Mauritius Rupee'}, + {'code' : 'MVR', 'name' : 'Maldives (Maldive Islands) Rufiyaa'}, + {'code' : 'MWK', 'name' : 'Malawi Kwacha'}, + {'code' : 'MXN', 'name' : 'Mexico Peso'}, + {'code' : 'MYR', 'name' : 'Malaysia Ringgit'}, + {'code' : 'MZN', 'name' : 'Mozambique Metical'}, + {'code' : 'NAD', 'name' : 'Namibia Dollar'}, + {'code' : 'NGN', 'name' : 'Nigeria Naira'}, + {'code' : 'NIO', 'name' : 'Nicaragua Cordoba'}, + {'code' : 'NOK', 'name' : 'Norway Krone'}, + {'code' : 'NPR', 'name' : 'Nepal Rupee'}, + {'code' : 'NZD', 'name' : 'New Zealand Dollar'}, + {'code' : 'OMR', 'name' : 'Oman Rial'}, + {'code' : 'PAB', 'name' : 'Panama Balboa'}, + {'code' : 'PEN', 'name' : 'Peru Nuevo Sol'}, + {'code' : 'PGK', 'name' : 'Papua New Guinea Kina'}, + {'code' : 'PHP', 'name' : 'Philippines Peso'}, + {'code' : 'PKR', 'name' : 'Pakistan Rupee'}, + {'code' : 'PLN', 'name' : 'Poland Zloty'}, + {'code' : 'PYG', 'name' : 'Paraguay Guarani'}, + {'code' : 'QAR', 'name' : 'Qatar Riyal'}, + {'code' : 'RON', 'name' : 'Romania New Leu'}, + {'code' : 'RSD', 'name' : 'Serbia Dinar'}, + {'code' : 'RUB', 'name' : 'Russia Ruble'}, + {'code' : 'RWF', 'name' : 'Rwanda Franc'}, + {'code' : 'SAR', 'name' : 'Saudi Arabia Riyal'}, + {'code' : 'SBD', 'name' : 'Solomon Islands Dollar'}, + {'code' : 'SCR', 'name' : 'Seychelles Rupee'}, + {'code' : 'SDG', 'name' : 'Sudan Pound'}, + {'code' : 'SEK', 'name' : 'Sweden Krona'}, + {'code' : 'SGD', 'name' : 'Singapore Dollar'}, + {'code' : 'SHP', 'name' : 'Saint Helena Pound'}, + {'code' : 'SLL', 'name' : 'Sierra Leone Leone'}, + {'code' : 'SOS', 'name' : 'Somalia Shilling'}, + {'code' : 'SPL', 'name' : 'Seborga Luigino'}, + {'code' : 'SRD', 'name' : 'Suriname Dollar'}, + {'code' : 'STD', 'name' : 'São Tomé and Príncipe Dobra'}, + {'code' : 'SVC', 'name' : 'El Salvador Colon'}, + {'code' : 'SYP', 'name' : 'Syria Pound'}, + {'code' : 'SZL', 'name' : 'Swaziland Lilangeni'}, + {'code' : 'THB', 'name' : 'Thailand Baht'}, + {'code' : 'TJS', 'name' : 'Tajikistan Somoni'}, + {'code' : 'TMT', 'name' : 'Turkmenistan Manat'}, + {'code' : 'TND', 'name' : 'Tunisia Dinar'}, + {'code' : 'TOP', 'name' : 'Tonga Pa\'anga'}, + {'code' : 'TRY', 'name' : 'Turkey Lira'}, + {'code' : 'TTD', 'name' : 'Trinidad and Tobago Dollar'}, + {'code' : 'TVD', 'name' : 'Tuvalu Dollar'}, + {'code' : 'TWD', 'name' : 'Taiwan New Dollar'}, + {'code' : 'TZS', 'name' : 'Tanzania Shilling'}, + {'code' : 'UAH', 'name' : 'Ukraine Hryvnia'}, + {'code' : 'UGX', 'name' : 'Uganda Shilling'}, + {'code' : 'USD', 'name' : 'United States Dollar'}, + {'code' : 'UYU', 'name' : 'Uruguay Peso'}, + {'code' : 'UZS', 'name' : 'Uzbekistan Som'}, + {'code' : 'VEF', 'name' : 'Venezuela Bolivar'}, + {'code' : 'VND', 'name' : 'Viet Nam Dong'}, + {'code' : 'VUV', 'name' : 'Vanuatu Vatu'}, + {'code' : 'WST', 'name' : 'Samoa Tala'}, + {'code' : 'XAF', 'name' : 'Communauté Financière Africaine (BEAC) CFA Franc BEAC'}, + {'code' : 'XCD', 'name' : 'East Caribbean Dollar'}, + {'code' : 'XDR', 'name' : 'International Monetary Fund (IMF) Special Drawing Rights'}, + {'code' : 'XOF', 'name' : 'Communauté Financière Africaine (BCEAO) Franc'}, + {'code' : 'XPF', 'name' : 'Comptoirs Français du Pacifique (CFP) Franc'}, + {'code' : 'YER', 'name' : 'Yemen Rial'}, + {'code' : 'ZAR', 'name' : 'South Africa Rand'}, + {'code' : 'ZMW', 'name' : 'Zambia Kwacha'}, + {'code' : 'ZWD', 'name' : 'Zimbabwe Dollar'} + ] + }; + + var o_hasOwnProperty = Object.prototype.hasOwnProperty; + var o_keys = (Object.keys || function(obj) { + var result = []; + for (var key in obj) { + if (o_hasOwnProperty.call(obj, key)) { + result.push(key); + } + } + + return result; + }); + + function _copyObject(source, target) { + var keys = o_keys(source); + var key; + + for (var i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + target[key] = source[key] || target[key]; + } + } + + function _copyArray(source, target) { + for (var i = 0, l = source.length; i < l; i++) { + target[i] = source[i]; + } + } + + function copyObject(source, _target) { + var isArray = Array.isArray(source); + var target = _target || (isArray ? new Array(source.length) : {}); + + if (isArray) { + _copyArray(source, target); + } else { + _copyObject(source, target); + } + + return target; + } + + /** Get the data based on key**/ + Chance.prototype.get = function (name) { + return copyObject(data[name]); + }; + + // Mac Address + Chance.prototype.mac_address = function(options){ + // typically mac addresses are separated by ":" + // however they can also be separated by "-" + // the network variant uses a dot every fourth byte + + options = initOptions(options); + if(!options.separator) { + options.separator = options.networkVersion ? "." : ":"; + } + + var mac_pool="ABCDEF1234567890", + mac = ""; + if(!options.networkVersion) { + mac = this.n(this.string, 6, { pool: mac_pool, length:2 }).join(options.separator); + } else { + mac = this.n(this.string, 3, { pool: mac_pool, length:4 }).join(options.separator); + } + + return mac; + }; + + Chance.prototype.normal = function (options) { + options = initOptions(options, {mean : 0, dev : 1}); + + // The Marsaglia Polar method + var s, u, v, norm, + mean = options.mean, + dev = options.dev; + + do { + // U and V are from the uniform distribution on (-1, 1) + u = this.random() * 2 - 1; + v = this.random() * 2 - 1; + + s = u * u + v * v; + } while (s >= 1); + + // Compute the standard normal variate + norm = u * Math.sqrt(-2 * Math.log(s) / s); + + // Shape and scale + return dev * norm + mean; + }; + + Chance.prototype.radio = function (options) { + // Initial Letter (Typically Designated by Side of Mississippi River) + options = initOptions(options, {side : "?"}); + var fl = ""; + switch (options.side.toLowerCase()) { + case "east": + case "e": + fl = "W"; + break; + case "west": + case "w": + fl = "K"; + break; + default: + fl = this.character({pool: "KW"}); + break; + } + + return fl + this.character({alpha: true, casing: "upper"}) + + this.character({alpha: true, casing: "upper"}) + + this.character({alpha: true, casing: "upper"}); + }; + + // Set the data as key and data or the data map + Chance.prototype.set = function (name, values) { + if (typeof name === "string") { + data[name] = values; + } else { + data = copyObject(name, data); + } + }; + + Chance.prototype.tv = function (options) { + return this.radio(options); + }; + + // ID number for Brazil companies + Chance.prototype.cnpj = function () { + var n = this.n(this.natural, 8, { max: 9 }); + var d1 = 2+n[7]*6+n[6]*7+n[5]*8+n[4]*9+n[3]*2+n[2]*3+n[1]*4+n[0]*5; + d1 = 11 - (d1 % 11); + if (d1>=10){ + d1 = 0; + } + var d2 = d1*2+3+n[7]*7+n[6]*8+n[5]*9+n[4]*2+n[3]*3+n[2]*4+n[1]*5+n[0]*6; + d2 = 11 - (d2 % 11); + if (d2>=10){ + d2 = 0; + } + return ''+n[0]+n[1]+'.'+n[2]+n[3]+n[4]+'.'+n[5]+n[6]+n[7]+'/0001-'+d1+d2; + }; + + // -- End Miscellaneous -- + + Chance.prototype.mersenne_twister = function (seed) { + return new MersenneTwister(seed); + }; + + // Mersenne Twister from https://gist.github.com/banksean/300494 + var MersenneTwister = function (seed) { + if (seed === undefined) { + seed = new Date().getTime(); + } + /* Period parameters */ + this.N = 624; + this.M = 397; + this.MATRIX_A = 0x9908b0df; /* constant vector a */ + this.UPPER_MASK = 0x80000000; /* most significant w-r bits */ + this.LOWER_MASK = 0x7fffffff; /* least significant r bits */ + + this.mt = new Array(this.N); /* the array for the state vector */ + this.mti = this.N + 1; /* mti==N + 1 means mt[N] is not initialized */ + + this.init_genrand(seed); + }; + + /* initializes mt[N] with a seed */ + MersenneTwister.prototype.init_genrand = function (s) { + this.mt[0] = s >>> 0; + for (this.mti = 1; this.mti < this.N; this.mti++) { + s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30); + this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253) + this.mti; + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + this.mt[this.mti] >>>= 0; + /* for >32 bit machines */ + } + }; + + /* initialize by an array with array-length */ + /* init_key is the array for initializing keys */ + /* key_length is its length */ + /* slight change for C++, 2004/2/26 */ + MersenneTwister.prototype.init_by_array = function (init_key, key_length) { + var i = 1, j = 0, k, s; + this.init_genrand(19650218); + k = (this.N > key_length ? this.N : key_length); + for (; k; k--) { + s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30); + this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + ((s & 0x0000ffff) * 1664525))) + init_key[j] + j; /* non linear */ + this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */ + i++; + j++; + if (i >= this.N) { this.mt[0] = this.mt[this.N - 1]; i = 1; } + if (j >= key_length) { j = 0; } + } + for (k = this.N - 1; k; k--) { + s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30); + this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941)) - i; /* non linear */ + this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */ + i++; + if (i >= this.N) { this.mt[0] = this.mt[this.N - 1]; i = 1; } + } + + this.mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */ + }; + + /* generates a random number on [0,0xffffffff]-interval */ + MersenneTwister.prototype.genrand_int32 = function () { + var y; + var mag01 = new Array(0x0, this.MATRIX_A); + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (this.mti >= this.N) { /* generate N words at one time */ + var kk; + + if (this.mti === this.N + 1) { /* if init_genrand() has not been called, */ + this.init_genrand(5489); /* a default initial seed is used */ + } + for (kk = 0; kk < this.N - this.M; kk++) { + y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk + 1]&this.LOWER_MASK); + this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1]; + } + for (;kk < this.N - 1; kk++) { + y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk + 1]&this.LOWER_MASK); + this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1]; + } + y = (this.mt[this.N - 1]&this.UPPER_MASK)|(this.mt[0]&this.LOWER_MASK); + this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; + + this.mti = 0; + } + + y = this.mt[this.mti++]; + + /* Tempering */ + y ^= (y >>> 11); + y ^= (y << 7) & 0x9d2c5680; + y ^= (y << 15) & 0xefc60000; + y ^= (y >>> 18); + + return y >>> 0; + }; + + /* generates a random number on [0,0x7fffffff]-interval */ + MersenneTwister.prototype.genrand_int31 = function () { + return (this.genrand_int32() >>> 1); + }; + + /* generates a random number on [0,1]-real-interval */ + MersenneTwister.prototype.genrand_real1 = function () { + return this.genrand_int32() * (1.0 / 4294967295.0); + /* divided by 2^32-1 */ + }; + + /* generates a random number on [0,1)-real-interval */ + MersenneTwister.prototype.random = function () { + return this.genrand_int32() * (1.0 / 4294967296.0); + /* divided by 2^32 */ + }; + + /* generates a random number on (0,1)-real-interval */ + MersenneTwister.prototype.genrand_real3 = function () { + return (this.genrand_int32() + 0.5) * (1.0 / 4294967296.0); + /* divided by 2^32 */ + }; + + /* generates a random number on [0,1) with 53-bit resolution*/ + MersenneTwister.prototype.genrand_res53 = function () { + var a = this.genrand_int32()>>>5, b = this.genrand_int32()>>>6; + return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); + }; + + + // CommonJS module + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = Chance; + } + exports.Chance = Chance; + } + + // Register as an anonymous AMD module + if (typeof define === 'function' && define.amd) { + define([], function () { + return Chance; + }); + } + + // if there is a importsScrips object define chance for worker + if (typeof importScripts !== 'undefined') { + chance = new Chance(); + } + + // If there is a window object, that at least has a document property, + // instantiate and define chance on the window + if (typeof window === "object" && typeof window.document === "object") { + window.Chance = Chance; + window.chance = new Chance(); + } +})(); diff --git a/grimoire-core.js b/grimoire-core.js new file mode 100644 index 0000000..2ef2df8 --- /dev/null +++ b/grimoire-core.js @@ -0,0 +1,361 @@ +//GrimoireJS v0.2 +//by Russell Champoux +//Grimoire magic item generator for the Pathfinder roleplaying game +/*global $:false, _:false, Chance:false, console:true */ + +'use strict'; + +var Grimoire = {}; +var TYPES = { + ARMOR_AND_SHIELDS: 'Armor and Shields', + POTIONS: 'Potions', + RINGS: 'Rings', + RODS: 'Rods', + SCROLLS: 'Scrolls', + STAVES: 'Staves', + WANDS: 'Wands', + WEAPONS: 'Weapons', + WONDROUS_ITEMS: 'Wondrous Items', + SPELLS: 'Spells' +}; +var SPELL_TYPES = { + ARCANE: 'Arcane', + DIVINE: 'Divine' +}; +var QUALITIES = { + MINOR:'minor', + MEDIUM: 'medium', + MAJOR: 'major' +}; +var WEIGHTS = {}; +WEIGHTS[QUALITIES.MINOR] = +{ + ARMOR_AND_SHIELDS: 4, + WEAPONS: 5, + POTIONS: 35, + RINGS: 2, + RODS: 0, + SCROLLS: 35, + STAVES: 0, + WANDS: 10, + WONDROUS_ITEMS: 9, +}; +WEIGHTS[QUALITIES.MEDIUM] = +{ + ARMOR_AND_SHIELDS: 10, + WEAPONS: 10, + POTIONS: 10, + RINGS: 10, + RODS: 10, + SCROLLS: 15, + STAVES: 3, + WANDS: 15, + WONDROUS_ITEMS: 17, +}; +WEIGHTS[QUALITIES.MAJOR] = { + ARMOR_AND_SHIELDS: 10, + WEAPONS: 10, + POTIONS: 5, + RINGS: 10, + RODS: 10, + SCROLLS: 10, + STAVES: 20, + WANDS: 5, + WONDROUS_ITEMS: 20, +}; + +//Contains all the source info +var SOURCES = []; +$.getJSON('sources/sources.json', function(sources) { + sources.sources.forEach(function(url) { + $.getJSON('sources/' + url, function(source) { + console.log('loaded sources/'+ url); + source.data = {}; + //construct the data containers we will insert later data into + source.types.forEach(function(type) { + source.data[type] = {}; + source.data[type].enabled = true; + var typeUrl = 'sources/' + source.shortName + '/' + type + '.json'; + $.getJSON(typeUrl, function(typeData) { + source.data[type].data = typeData.data; + console.log('loaded sources/' + typeUrl); + }) + .fail(function(d, textStatus, error) { + console.error('getJSON failed to load '+typeUrl+ ', status: ' + textStatus + ', error: '+error); + }); + }); + SOURCES.push(source); + }) + .fail(function(d, textStatus, error) { + console.error('getJSON failed to load '+url+ ', status: ' + textStatus + ', error: '+error); + }); + }); + }) + .fail(function(err) { + console.log('Failed to load sources list:', err); + }); + +Grimoire.getItems = function(sources, quality, count, types, options) { + + var items = []; + + //Error checking block + if(!sources || sources.length === 0) { console.log('No sources given!'); return items; } + if(!types || types == 'any' || types.length === 0) { + types = _.values(TYPES); //set to all types + } + for(var i in types) { + if(_.values(TYPES).indexOf(types[i]) == -1) { console.log('Invalid type ' + types[i]); return items; } + } + if(_.values(QUALITIES).indexOf(quality) == -1) { console.log('Invalid quality ' + quality); return items; } + if(!count || count < 1) { count = 1; } + options = options ? options : {}; + + + + //initialize the chance engine, using a seed if provided (for testing purposes) + //we do this now instead of reinitializing the Chance engine each time we generate an item + options.chance = (options.chance ? options.chance : options.seed ? new Chance(options.seed) : new Chance()); + + _.times(count, function() { + var item = Grimoire.getItem(sources, quality, types, options); + if(item) { + items.push(item); + console.log(item); + } + }); + return items; +}; + +var selectSource = function(sources, quality, type, options) { + options = options ? options : {}; + var chance = (options.chance ? options.chance : options.seed ? new Chance(options.seed) : new Chance()); + + var source = {}; + var sourceWeights = {}; + + //***SPELLS AND SCROLLS*** + //************************ + if(type == TYPES.SCROLLS || type == TYPES.SPELLS) { + if(!options.spellType || !options.spellLevel) { + console.log('Error selecting source for Spells. Invalid options', options); + } + sourceWeights = _.map(sources, function(source) { + if(source.data.Spells && source.data.Spells.enabled) { + if(source.data.Spells.data[options.spellType]) { + return source.data[type].data[options.spellType][options.spellLevel].length; + } + else { //source did not have my desired spell type + return 0; + } + } + else { //source has no spells + return 0; + } + + }); + } + //***WONDROUS ITEMS*** + //******************** + else if(type == TYPES.WONDROUS_ITEMS) { + sourceWeights = _.map(sources, + function(source) { + if(source.data[type] && source.data[type].enabled && source.data[type].data[quality]) { + return source.data[type].data[quality].length; + } + else { + return 0; //either no data, disabled, or not items of that quality + } + }); + } + //***EVERYTHING ELSE*** + //********************* + else { + if(type == TYPES.RODS && quality == QUALITIES.MINOR) { + console.log('Error! There are no ' + QUALITIES.MINOR + ' ' + TYPES.RODS); + return; + } + //Determine which source to use + //get a count from each source of what we're looking for + sourceWeights = _.map(sources, + function(source) { + //only choose from sources that HAVE that type of item + //AND are enabled + //AND have at least one item of that quality with a probability weight + if(source.data[type] && source.data[type].enabled) { + return _.filter(source.data[type].data, + function(item) { + return item.weight[quality] > 0; + }).length; + } + else { + return 0; + } + }); + } + if(_.sum(sourceWeights) <= 0) { + console.log('Unable to find valid ' + quality + ' ' + type + ' within sources!', sources); + return; + } + //chance.weighted will DESTRUCTIVELY modify paramaters that have a weight of zero + //in this case, that means sources that do not contain the selected type + //or sources that have types we want but with no weight + //because of that, I create a temp array that I don't care if chance mangles + source = sources[chance.weighted(_.range(sources.length), sourceWeights)]; + return source; +}; + + +Grimoire.getItem = function(sources, quality, types, options) { + options = options ? options : {}; + + var chance = (options.chance ? options.chance : options.seed ? new Chance(options.seed) : new Chance()); + + var itemType = ''; + if(types.length == 1) { + itemType = types[0]; + } + else { + //Create a weighted-average map based on the desired types + var localWeights = _.clone(WEIGHTS[quality]); //copy the default weighted-average for this quality + for(var key in localWeights) { + if(_.values(types).indexOf(TYPES[key]) == -1) { //remove any items that were not selected + delete localWeights[key]; + } + } + //Determine the type of item to generate + //console.log(localWeights); + itemType = TYPES[chance.weighted(_.keys(localWeights), _.values(localWeights))]; + } + + var item = {}; + var source = {}; + + //GENERATE ITEM + //SCROLLS + if(itemType == TYPES.SCROLLS) { + item = Grimoire.getScroll(sources, quality, undefined /*spell type*/, options); + } + //WONDROUS ITEMS + else if(itemType == TYPES.WONDROUS_ITEMS) { + //Select the item source based on the quality and item type + source = selectSource(sources, quality, itemType, options); + item = _.clone(chance.pick(source.data[itemType].data[quality])); + item.source = source.shortName; + if(options.allIntelligent || (!options.disableIntelligent && chance.d100() == 1)) { + item.intelligence = 'WOOHOO I AM INTELLIGENT!'; + } + } + //EVERYTHING ELSE + else { + //Select the item source based on the quality and item type + source = selectSource(sources, quality, itemType, options); + var totalWeights = _.sum(_.map(source.data[itemType].data, function(item) { return item.weight[quality]; })); + var roll = chance.integer({min: 1, max: totalWeights}); + + //EXCEPTIONS FOR ARMOR_AND_SHEILDS + + //EXCEPTIONS FOR WEAPONS + + //EXCEPTIONS FOR POTIONS + + //EXCEPTIONS FOR WANDS + + //CHANCE FOR INTELLIGENT WEAPONS, RINGS, RODS, STAVES, OR WONDROUS ITEMS + var itemData = source.data[itemType].data; + for(var i in itemData) { //check all 'itemType' items in the source + if(roll <= itemData[i].weight[quality]) { //if we roll under their weighted probability + item = _.clone(itemData[i]); + delete item.weight; + item.source = source.shortName; + break; + } + else { //decrease the roll value by the current item's weighted probability + roll -= itemData[i].weight[quality]; + } + } + } + item.quality = quality; + return item; +}; + +Grimoire.getSpells = function(sources, level, count, type, options) { + options = options ? options : {}; + + var spells = []; + options.chance = (options.chance ? options.chance : options.seed ? new Chance(options.seed) : new Chance()); + + _.times(count, function() { + + spells.push(Grimoire.getSpell(sources, level, type, options)); + }); + + return spells; +}; + +Grimoire.getSpell = function(sources, level, type, options) { + options = options ? options : {}; + + //initialize the chance engine, using a seed if provided (for testing purposes) + var chance = (options.chance ? options.chance : options.seed ? new Chance(options.seed) : new Chance()); + + var spellType = type ? type : chance.pick(_.values(SPELL_TYPES)); + options.spellType = spellType; + options.spellLevel = level; + var source = selectSource(sources, undefined, TYPES.SPELLS, options); + //console.log('Generating a level ' + level + ' ' + spellType + ' spell from ' + source.shortName); + + var spell = { + name: chance.pick(source.data.Spells.data[spellType][level]), + level: level, + type: spellType, + source: source.shortName + }; + + return spell; +}; + +Grimoire.getScroll = function(sources, quality, type, options) { + options = options ? options : {}; + var chance = (options.chance ? options.chance : options.seed ? new Chance(options.seed) : new Chance()); + + var cost = [12.5, 25, 150, 375, 700, 1125, 1650, 2275, 3000, 3825]; + var spellLevel = 0; + + var roll = chance.integer({min: 1, max: 100}); + if(quality == QUALITIES.MINOR) { + switch(true) { + case (roll <= 5): spellLevel = 0; break; + case (roll <= 50): spellLevel = 1; break; + case (roll <= 95): spellLevel = 2; break; + case (roll <= 100): spellLevel = 3; break; + } + } + else if(quality == QUALITIES.MEDIUM) { + switch(true) { + case (roll <= 5): spellLevel = 2; break; + case (roll <= 65): spellLevel = 3; break; + case (roll <= 95): spellLevel = 4; break; + case (roll <= 100): spellLevel = 5; break; + } + } + else if(quality == QUALITIES.MAJOR) { + switch(true) { + case (roll <= 5): spellLevel = 4; break; + case (roll <= 50): spellLevel = 5; break; + case (roll <= 70): spellLevel = 6; break; + case (roll <= 85): spellLevel = 7; break; + case (roll <= 95): spellLevel = 8; break; + case (roll <= 100): spellLevel = 9; break; + } + } + + var spell = Grimoire.getSpell(sources, spellLevel, type, options); + + return { + 'name': 'Scroll of ' + spell.name, + 'description': '(' + spell.type + ', spell level ' + spellLevel + ', caster level ' + _.max([1, (spellLevel*2-1)]) + ')', + 'cost': cost[spellLevel], + 'source': spell.source + }; +}; \ No newline at end of file diff --git a/index.html b/index.html index 28f1fe6..490240a 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,12 @@ GrimoireJS - + + + + + +

GrimoireJS

diff --git a/sources/APG.json b/sources/APG.json new file mode 100644 index 0000000..f23e2ee --- /dev/null +++ b/sources/APG.json @@ -0,0 +1,10 @@ +{ + "name": "Advanced Player's Guide", + "shortName": "APG", + "types": [ + "Rings", + "Rods", + "Spells", + "Wondrous Items" + ] +} \ No newline at end of file diff --git a/sources/APG/Rings.json b/sources/APG/Rings.json new file mode 100644 index 0000000..6f185ac --- /dev/null +++ b/sources/APG/Rings.json @@ -0,0 +1,22 @@ +{ + "data": [ + { "name" : "Dungeon ring, prisoner's", "cost": 250, "url": "#dungeon-ring", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Arcane signets", "cost": 1000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Maniacal Devices", "cost": 5000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (1 stone)", "cost": 5000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Forcefangs", "cost": 8000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Revelation, lesser", "cost": 10000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (2 stones)", "cost": 10000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (3 stones)", "cost": 15000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Retribution", "cost": 15000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Dungeon ring, jailer's", "cost": 16000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Revelation, greater", "cost": 16000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (4 stones)", "cost": 20000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Revelation, superior", "cost": 24000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (5 stones)", "cost": 25000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (6 stones)", "cost": 30000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (7 stones)", "cost": 35000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (8 stones)", "cost": 40000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Delayed doom (9 stones)", "cost": 45000, "url": "", "weight": {"minor": 0, "medium": 0, "major": 0} } + ] +} \ No newline at end of file diff --git a/sources/APG/Rods.json b/sources/APG/Rods.json new file mode 100644 index 0000000..9ef5d17 --- /dev/null +++ b/sources/APG/Rods.json @@ -0,0 +1,47 @@ +{ + "_todo": "Add weights!", + "data": [ + {"name": "Rod of Metamagic, merciful, lesser", "cost": 1500, "url": "#metamagic,-merciful", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, bouncing, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, disruptive, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, ectoplasmic, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, elemental, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, focused, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, intensified, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, lingering, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, reach, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, selective, lesser", "cost": 3000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, merciful", "cost": 5500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, persistent, lesser", "cost": 9000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, sickening, lesser", "cost": 9000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, thundering, lesser", "cost": 9000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, bouncing", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, disruptive", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, ectoplasmic", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, elemental", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, focused", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, intensified", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, lingering", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, reach", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, selective", "cost": 11000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, merciful, greater", "cost": 12250, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, dazing, lesser", "cost": 14000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, bouncing, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, disruptive, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, ectoplasmic, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, elemental, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, focused, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, intensified, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, lingering, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, reach, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, selective, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, persistent", "cost": 32500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, sickening", "cost": 32500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, thundering", "cost": 32500, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, dazing", "cost": 54000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, persistent, greater", "cost": 73000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, sickening, greater", "cost": 73000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, thundering, greater", "cost": 73000, "url": "", "weight": {"medium": 0, "major": 0} }, + {"name": "Rod of Metamagic, dazing, greater", "cost": 121500, "url": "", "weight": {"medium": 0, "major": 0} } + ] +} \ No newline at end of file diff --git a/sources/APG/Spells.json b/sources/APG/Spells.json new file mode 100644 index 0000000..b57f303 --- /dev/null +++ b/sources/APG/Spells.json @@ -0,0 +1,70 @@ +{ + "data": { + "Arcane": [ + ["Sift", "Spark", "Unwitting Ally", "Message", "Acid Splash", "Ray of Frost", "Putrefy Food and Drink"], + ["Beguiling Gift", "Borrow Skill", "Dancing Lantern", "Feather Step", "Flare Burst", "Innocence", "Invigorate", "Memory Lapse", + "Restful Sleep", "Saving Finale", "Share Language", "Solid Note", "Timely Inspiration", "Touch of Gracelessness", "Vanish", "Alter Winds", "Feather Fall", + "Shocking Grasp", "Expeditious Excavation", "Grease", "Stone Fist", "Burning Hands", "Hydraulic Push", "Obscuring Mist", "Touch of the Sea", "Ant Haul", + "Break", "Crafter's Curse", "Crafter's Fortune", "Gravity Bow", "Sculpt Corpse", "Stumble Gap", "Rejuvenate Eidolon, Lesser", "Unfetter", "Ill Omen", + "Mask Dweomer"], + ["Blood Biography", "Cacophonous Call", "Create Treasure Map", "Dust of Twilight", "Enter Image", "Gallant Inspiration", + "Ghostbane Dirge", "Hidden Speech", "Honeyed Tongue", "Versatile Weapon", "Elemental Speech", "Elemental Touch", "Resist Energy", "Summon Monster II", + "Glide", "Gust of Wind", "Levitate", "Whispering Wind", "Acid Arrow", "Create Pit", "Glitterdust", "Shatter", "Stone Call", "Burning Gaze", "Fire Breath", + "Flaming Sphere", "Pyrotechnics", "Scorching Ray", "Accelerate Poison", "Fog Cloud", "Slipstream", "Arrow Eruption", "Create Treasure Map", "Share Language", + "Create Pit", "Evolution Surge, Lesser", "Summon Eidolon", "Feast of Ashes", "Fester", "Perceive Cues", "Pox Pustules", "Vomit Swarm"], + ["Arcane Concordance", "Campfire Wall", "Coordinated Effort", "Elemental Speech", "Feather Step, Mass", "Invigorate, Mass", + "Jester's Jaunt", "Purging Finale", "Reviving Finale", "Seek Thoughts", "Thunderous Drums", "Draconic Reservoir", "Elemental Aura", "Protection From Energy", + "Cloak of Winds", "Fly", "Gaseous Form", "Lightning Bolt", "Wind Wall", "Shifting Sand", "Spiked Pit", "Stinking Cloud", "Fireball", "Flame Arrow", "Aqueous Orb", + "Hydraulic Torrent", "Sleet Storm", "Water Breathing", "Blood Biography", "Devolution", "Enter Image", "Pain Strike", "Twilight Knife", "Versatile Weapon", + "Evolution Surge", "Rejuvenate Eidolon", "Cup of Dust", "Guiding Star", "Nature's Exile", "Screech", "Share Senses"], + ["Denounce", "Discordant Blast", "Ghostbane Dirge, Mass", "Heroic Finale", "Treasure Stitching", "Wandering Star Motes", "Detonate", + "Dragon's Breath", "Elemental Body I", "Summon Monster IV", "Ball Lightning", "River of Wind", "Shout", "Acid Pit", "Calcific Touch", "Stone Shape", "Stoneskin", + "Fire Shield", "Fire Trap", "Firefall", "Wall of Fire", "Ice Storm", "Solid Fog", "Wall of Ice", "Acid Pit", "Detonate", "Moonstruck", "Shadow Projection", + "Share Senses", "True Form", "Evolution Surge, Greater", "Purified Calling", "Transmogrify", "Sleepwalk", "Spite", "Threefold Aspect"], + ["Bard's Escape", "Cacophonous Call, Mass", "Cloak of Dreams", "Deafening Song Bolt", "Foe to Friend", "Frozen Note", "Phantasmal Web", + "Stunning Finale", "Unwilling Shield", "Elemental Body II", "Planar Adaptation", "Planar Binding, Lesser", "Summon Monster V", "Overland Flight", "Suffocation", + "Hungry Pit", "Passwall", "Transmute Mud to Rock", "Transmute Rock to Mud", "Wall of Stone", "Fire Snake", "Geyser", "Cloudkill", "Cone of Cold", + "Life Bubble", "Pain Strike, Mass", "Treasure Stitching", "Rejuvenate Eidolon, Greater", "Banish Seeming", "Rest Eternal"], + ["Brilliant Inspiration", "Deadly Finale", "Euphoric Tranquility", "Fool's Forbiddance", "Getaway", "Pied Piping", "Elemental Body III", + "Planar Binding", "Summon Monster VI", "Chain Lightning", "Sirocco", "Acid Fog", "Flesh to Stone", "Move Earth", "Stone to Flesh", "Wall of Iron", + "Contagious Flame", "Fluid Form", "Freezing Sphere", "Cloak of Dreams", "Enemy Hammer", "Unwilling Shield", "Planar Adaptation, Mass", "Fester, Mass", + "Swarm Skin"], + ["Elemental Body IV", "Planar Adaptation, Mass", "Summon Monster VII", "Control Weather", "Fly, Mass", "Rampart", "Reverse Gravity", + "Statue", "Delayed Blast Fireball", "Firebrand", "Vortex", "Deflection", "Expend", "Phantasmal Revenge"], + ["Planar Binding, Greater", "Summon Monster VII", "Shout, Greater", "Stormbolts", "Iron Body", "Wall of Lava", "Incendiary Cloud", + "Horrid Wilting", "Polar Ray", "Seamantle", "Euphoric Tranquility"], + ["Gate", "Suffocation, Mass", "Winds of Vengeance", "Clashing Rocks", "World Wave", "Fiery Body", "Meteor Swarm", "Tsunami", "Tsunami", + "Wall of SuppressionM"] + ], + "Divine" : [ + ["Spark", "Brand", "Sift"], + ["Ant Haul", "Dancing Lantern", "Alter Winds", "Aspect of the Falcon", "Bristle", "Call Animal", "Cloak of Shade", "Detect Aberration", + "Expeditious Excavation", "Feather Step", "Flare Burst", "Hydraulic Push", "Keen Senses", "Negate Aroma", "Stone Fist", "Touch of the Sea", "Burst Bonds", + "Tireless Pursuit", "Wrath", "Challenge Evil", "Ghostbane Dirge", "Grace", "Hero's Defiance", "Honeyed Tongue", "Knight's Calling", "Rally Point", + "Veil of Positive Energy", "Glide", "Gravity Bow", "Hunter's Howl", "Lead Blades", "Residual Tracking"], + ["Blessing of Courage and Life", "Ghostbane Dirge", "Grace", "Instant Armor", "Oracle's Burden", "Share Language", "Weapon of Awe", + "Accelerate Poison", "Aspect of the Bear", "Burning Gaze", "Campfire Wall", "Eagle Eye", "Elemental Speech", "Feast of Ashes", "Glide", "Lockjaw", + "Natural Rhythm", "Pox Pustules", "Scent Trail", "Slipstream", "Stone Call", "Bloodhound", "Castigate", "Confess", "Corruption Resistance", + "Flames of the Faithful", "Follow Aura", "Honeyed Tongue", "Perceive Cues", "Sacred Bond", "Aura of Greater Courage", "Bestow Grace", "Fire of Entanglement", + "Light Lance", "Paladin's Sacrifice", "Righteous Vigor", "Saddle Surge", "Wake of Light", "Allfood", "Arrow Eruption", "Chameleon Stride", + "Create Treasure Map", "Guiding Star", "Hide Campsite", "Hunter's Eye", "Protective Spirit", "Versatile Weapon"], + ["Blood Biography", "Borrow Fortune", "Elemental Speech", "Enter Image", "Guiding Star", "Nap Stack", "Sacred Bond", "Wrathful Mantle", + "Aqueous Orb", "Cloak of Winds", "Create Treasure Map", "Cup of Dust", "Feather Step, Mass", "Hide Campsite", "Hydraulic Torrent", "Lily Pad Stride", + "Nature's Exile", "Shifting Sand", "Banish Seeming", "Cast Out", "Coordinated Effort", "Fester", "Hidden Speech", "Hunter's Eye", "Retribution", + "Righteous Vigor", "Seek Thoughts", "Ward the Faithful", "Divine Transfer", "Fire of Judgment", "Ghostbane Dirge, Mass", "Holy Whisper", + "Marks of Forbiddance", "Sanctify Armor", "Aspect of the Stag", "Bloody Claws", "Instant Enemy", "Life Bubble", "Strong Jaw", "Tireless Pursuers", + "Venomous Bolt"], + ["Blessing of Fervor", "Planar Adaptation", "Rest Eternal", "Spiritual Ally", "Aspect of the Stag", "Ball Lightning", "Bloody Claws", + "Geyser", "Grove of Respite", "Life Bubble", "Moonstruck", "River of Wind", "Strong Jaw", "Thorn Body", "True Form", "Brand, Greater", "Coward's Lament", + "Defile Armor", "Denounce", "Forced Repentance", "Rebuke", "Sanctify Armor", "Shared Wrath", "Sleepwalk", "Tireless Pursuers", "Blaze of Glory", + "Fire of Vengeance", "King's Castle", "Oath of Peace", "Resounding Blow", "Sacrificial Oath", "Stay the Hand", "Aspect of the Wolf", + "Blessing of the Salamander", "Bow Spirit"], + ["Cleanse", "Ghostbane Dirge, Mass", "Life Bubble", "Pillar of Life", "Snake Staff", "Treasure Stitching", "Aspect of the Wolf", + "Blessing of the Salamander", "Fire Snake", "Rest Eternal", "Threefold Aspect", "Castigate, Mass", "Resounding Blow", "Unwilling Shield"], + ["Planar Adaptation, Mass", "Sirocco", "Swarm Skin", "Cleanse", "Fester, Mass"], + ["Rampart", "Vortex"], + ["Divine Vessel", "Euphoric Tranquility", "Stormbolts", "Seamantle", "Wall of Lava"], + ["Winds of Vengeance", "Clashing Rocks", "Tsunami", "World Wave"] + ] + } +} \ No newline at end of file diff --git a/sources/APG/Wondrous Items.json b/sources/APG/Wondrous Items.json new file mode 100644 index 0000000..0fb7e91 --- /dev/null +++ b/sources/APG/Wondrous Items.json @@ -0,0 +1,72 @@ +{ + "data": { + "minor" : [ + {"name": "Ioun torch", "cost": 75, "url": "#_ioun-torch"}, + {"name": "War paint of the terrible visage", "cost" : 100, "url" : ""}, + {"name": "Assisting glove", "cost" : 180, "url" : ""}, + {"name": "Bandages of rapid recovery", "cost" : 200, "url" : ""}, + {"name": "Catching cape", "cost" : 200, "url" : ""}, + {"name": "Soul soap", "cost" : 200, "url" : ""}, + {"name": "Bottle of messages", "cost" : 300, "url" : ""}, + {"name": "Key of lock jamming", "cost" : 400, "url" : ""}, + {"name": "Campfire bead", "cost" : 720, "url" : ""}, + {"name": "Defoliant polish", "cost" : 800, "url" : ""}, + {"name": "Dust of emulation", "cost" : 800, "url" : ""}, + {"name": "Muleback cords", "cost" : 1000, "url" : ""}, + {"name": "All tools vest", "cost" : 1800, "url" : ""}, + {"name": "Cowardly crouching cloak", "cost" : 1800, "url" : ""}, + {"name": "Scabbard of vigor", "cost" : 1800, "url" : ""}, + {"name": "Clamor box", "cost" : 2000, "url" : ""}, + {"name": "Glowing glove", "cost" : 2000, "url" : ""}, + {"name": "Manacles of cooperation", "cost" : 2000, "url" : ""}, + {"name": "Knight's pennon (honor)", "cost" : 2200, "url" : ""}, + {"name": "Flying ointment", "cost" : 2250, "url" : ""}, + {"name": "Boots of friendly terrain", "cost" : 2400, "url" : ""}, + {"name": "Apple of eternal sleep", "cost" : 2500, "url" : ""}, + {"name": "Cauldron of brewing", "cost" : 3000, "url" : ""}, + {"name": "Philter of love", "cost" : 3000, "url" : ""}, + {"name": "Sash of the war champion", "cost" : 4000, "url" : ""}, + {"name": "Knight's pennon (battle)", "cost" : 4500, "url" : ""}, + {"name": "Knight's pennon (parley)", "cost" : 4500, "url" : ""}, + {"name": "Helm of fearsome mien", "cost" : 5000, "url" : ""}, + {"name": "Horn of the huntmaster", "cost" : 5000, "url" : ""}, + {"name": "Scabbard of staunching", "cost" : 5000, "url" : ""}, + {"name": "Sheath of bladestealth", "cost" : 5000, "url" : ""} + ], + "medium": [ + {"name": "Grappler's mask", "cost": 5000, "url": "#grappler's-mask"}, + {"name": "Torc of lionheart fury", "cost": 8000, "url": ""}, + {"name": "Amulet of spell cunning", "cost": 10000, "url": ""}, + {"name": "Construct channel brick", "cost": 10000, "url": ""}, + {"name": "Doomharp", "cost": 10000, "url": ""}, + {"name": "Ki mat", "cost": 10000, "url": ""}, + {"name": "Lord's banner (swiftness)", "cost": 10000, "url": ""}, + {"name": "Crystal of healing hands", "cost": 12000, "url": ""}, + {"name": "Book of the loremaster", "cost": 15000, "url": ""}, + {"name": "Bracelet of mercy", "cost": 15000, "url": ""}, + {"name": "Cauldron of plenty", "cost": 15000, "url": ""}, + {"name": "Gloves of dueling", "cost": 15000, "url": ""}, + {"name": "Necklace of ki serenity", "cost": 16000, "url": ""}, + {"name": "Robes of arcane heritage", "cost": 16000, "url": ""}, + {"name": "Silver smite bracelet", "cost": 16000, "url": ""}, + {"name": "Vest of the cockroach", "cost": 16000, "url": ""}, + {"name": "Amulet of magecraft", "cost": 20000, "url": ""}, + {"name": "Horn of antagonism", "cost": 20000, "url": ""}, + {"name": "Moon circlet", "cost": 20000, "url": ""}, + {"name": "Necromancer's athame", "cost": 20000, "url": ""}, + {"name": "Sniper goggles", "cost": 20000, "url": ""}, + {"name": "Annihilation spectacles", "cost": 25000, "url": ""} + ], + "major": [ + {"name": "Cauldron of the dead", "cost": 30000, "url": "#cauldron-of-the-dead"}, + {"name": "Mask of giants (lesser)", "cost": 30000, "url": ""}, + {"name": "Cauldron of resurrection", "cost": 33000, "url": ""}, + {"name": "Cauldron of flying", "cost": 40000, "url": ""}, + {"name": "Cauldron of seeing", "cost": 42000, "url": ""}, + {"name": "Lord's banner (terror)", "cost": 56000, "url": ""}, + {"name": "Lord's banner (victory)", "cost": 75000, "url": ""}, + {"name": "Mask of giants (greater)", "cost": 90000, "url": ""}, + {"name": "Lord's banner (crusades)", "cost": 100000, "url": ""} + ] + } +} \ No newline at end of file diff --git a/sources/CRB.json b/sources/CRB.json new file mode 100644 index 0000000..08c10b6 --- /dev/null +++ b/sources/CRB.json @@ -0,0 +1,11 @@ +{ + "_todo": "Add the following items Armor and Shields, Potions, Rods, Scrolls, Staves, Wands, Weapons", + "name": "Core Rule Book", + "shortName": "CRB", + "types": [ + "Rings", + "Rods", + "Spells", + "Wondrous Items" + ] +} \ No newline at end of file diff --git a/sources/CRB/Rings.json b/sources/CRB/Rings.json new file mode 100644 index 0000000..13290c8 --- /dev/null +++ b/sources/CRB/Rings.json @@ -0,0 +1,50 @@ +{ +"data": [ + { "name" : "Ring of Protection +1", "cost" : 2000, "url" : "#_ring-of-protection", "weight": {"minor": 18, "medium": 0, "major": 0} }, + { "name" : "Ring of Feather falling", "cost" : 2200, "url" : "", "weight": {"minor": 10, "medium": 0, "major": 0} }, + { "name" : "Ring of Sustenance", "cost" : 2500, "url" : "", "weight": {"minor": 8, "medium": 0, "major": 0} }, + { "name" : "Ring of Climbing", "cost" : 2500, "url" : "", "weight": {"minor": 8, "medium": 0, "major": 0} }, + { "name" : "Ring of Jumping", "cost" : 2500, "url" : "", "weight": {"minor": 8, "medium": 0, "major": 0} }, + { "name" : "Ring of Swimming", "cost" : 2500, "url" : "", "weight": {"minor": 8, "medium": 0, "major": 0} }, + { "name" : "Ring of Counterspells", "cost" : 400, "url" : "", "weight": {"minor": 10, "medium": 5, "major": 0} }, + { "name" : "Ring of Mind shielding", "cost" : 800, "url" : "", "weight": {"minor": 5, "medium": 3, "major": 0} }, + { "name" : "Ring of Protection +2", "cost" : 8000, "url" : "", "weight": {"minor": 5, "medium": 10, "major": 0} }, + { "name" : "Ring of Force shield", "cost" : 8500, "url" : "", "weight": {"minor": 5, "medium": 0, "major": 0} }, + { "name" : "Ring of the Ram", "cost" : 8600, "url" : "", "weight": {"minor": 5, "medium": 0, "major": 0} }, + { "name" : "Ring of Climbing, improved", "cost" : 1000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Jumping, improved", "cost" : 1000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Swimming, improved", "cost" : 1000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Animal friendship", "cost" : 10800, "url" : "", "weight": {"minor": 3, "medium": 0, "major": 0} }, + { "name" : "Ring of Energy resistance, minor", "cost" : 1200, "url" : "", "weight": {"minor": 3, "medium": 0, "major": 0} }, + { "name" : "Ring of Chameleon power", "cost" : 12700, "url" : "", "weight": {"minor": 2, "medium": 0, "major": 0} }, + { "name" : "Ring of Water walking", "cost" : 1500, "url" : "", "weight": {"minor": 2, "medium": 0, "major": 0} }, + { "name" : "Ring of Protection +3", "cost" : 1800, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Spell storing, minor", "cost" : 1800, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Invisibility", "cost" : 20000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Wizardry (I)", "cost" : 2000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Evasion", "cost" : 2500, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of X-ray vision", "cost" : 2500, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Blinking", "cost" : 2700, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Energy resistance, major", "cost" : 2800, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Protection +4", "cost" : 3200, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Wizardry (II)", "cost" : 4000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Freedom of movement", "cost" : 4000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Energy resistance, greater", "cost" : 4400, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Friend shield (pair)", "cost" : 5000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Protection +5", "cost" : 5000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Shooting stars", "cost" : 5000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Spell storing", "cost" : 5000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Wizardry (III)", "cost" : 7000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Telekinesis", "cost" : 7500, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Regeneration", "cost" : 9000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Spell turning", "cost" : 10000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Wizardry (IV)", "cost" : 10000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Three wishes", "cost" : 12000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Djinni calling", "cost" : 12500, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Elemental command (air)", "cost" : 20000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Elemental command (earth)", "cost" : 20000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Elemental command (fire)", "cost" : 20000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Elemental command (water)", "cost" : 20000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} }, + { "name" : "Ring of Spell storing, major", "cost" : 2000, "url" : "", "weight": {"minor": 0, "medium": 0, "major": 0} } + ] + } \ No newline at end of file diff --git a/sources/CRB/Rods.json b/sources/CRB/Rods.json new file mode 100644 index 0000000..70a6469 --- /dev/null +++ b/sources/CRB/Rods.json @@ -0,0 +1,41 @@ +{ + "_todo": "Add weights!", + "data": [ + {"name": "Rod of Metamagic, Enlarge, lesser", "cost": 3000, "url": "#metamagic-enlarge", "weight": {"medium": 7, "major": 0} }, + {"name": "Rod of Metamagic, Extend, lesser", "cost": 3000, "url": "", "weight": {"medium": 7, "major": 0} }, + {"name": "Rod of Metamagic, Silent, lesser", "cost": 3000, "url": "", "weight": {"medium": 7, "major": 0} }, + {"name": "Rod of Immovable", "cost": 5000, "url": "", "weight": {"medium": 7, "major": 0} }, + {"name": "Rod of Metamagic, Empower, lesser", "cost": 9000, "url": "", "weight": {"medium": 7, "major": 0} }, + {"name": "Rod of Metal and mineral detection", "cost": 10500, "url": "", "weight": {"medium": 7, "major": 0} }, + {"name": "Rod of Cancellation", "cost": 11000, "url": "", "weight": {"medium": 11, "major": 4} }, + {"name": "Rod of Metamagic, Enlarge", "cost": 11000, "url": "", "weight": {"medium": 4, "major": 2} }, + {"name": "Rod of Metamagic, Extend", "cost": 11000, "url": "", "weight": {"medium": 4, "major": 2} }, + {"name": "Rod of Metamagic, Silent", "cost": 11000, "url": "", "weight": {"medium": 4, "major": 2} }, + {"name": "Rod of Wonder", "cost": 12000, "url": "", "weight": {"medium": 6, "major": 4} }, + {"name": "Rod of Python", "cost": 13000, "url": "", "weight": {"medium": 8, "major": 5} }, + {"name": "Rod of Metamagic, Maximize, lesser", "cost": 14000, "url": "", "weight": {"medium": 4, "major": 0} }, + {"name": "Rod of Flame extinguishing", "cost": 15000, "url": "", "weight": {"medium": 6, "major": 2} }, + {"name": "Rod of Viper", "cost": 19000, "url": "", "weight": {"medium": 8, "major": 4} }, + {"name": "Rod of Enemy detection", "cost": 23500, "url": "", "weight": {"medium": 0, "major": 5} }, + {"name": "Rod of Metamagic, Enlarge, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 6} }, + {"name": "Rod of Metamagic, Extend, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 6} }, + {"name": "Rod of Metamagic, Silent, greater", "cost": 24500, "url": "", "weight": {"medium": 0, "major": 6} }, + {"name": "Rod of Splendor", "cost": 25000, "url": "", "weight": {"medium": 0, "major": 5} }, + {"name": "Rod of Withering", "cost": 25000, "url": "", "weight": {"medium": 0, "major": 5} }, + {"name": "Rod of Metamagic, Empower", "cost": 32500, "url": "", "weight": {"medium": 2, "major": 6} }, + {"name": "Rod of Thunder and lightning", "cost": 33000, "url": "", "weight": {"medium": 0, "major": 5} }, + {"name": "Rod of Metamagic, Quicken, lesser", "cost": 35000, "url": "", "weight": {"medium": 1, "major": 4} }, + {"name": "Rod of Negation", "cost": 37000, "url": "", "weight": {"medium": 0, "major": 4} }, + {"name": "Rod of Absorption", "cost": 50000, "url": "", "weight": {"medium": 0, "major": 3} }, + {"name": "Rod of Flailing", "cost": 50000, "url": "", "weight": {"medium": 0, "major": 4} }, + {"name": "Rod of Metamagic, Maximize", "cost": 54000, "url": "", "weight": {"medium": 0, "major": 2} }, + {"name": "Rod of Rulership", "cost": 60000, "url": "", "weight": {"medium": 0, "major": 2} }, + {"name": "Rod of Security", "cost": 61000, "url": "", "weight": {"medium": 0, "major": 2} }, + {"name": "Rod of Lordly might", "cost": 70000, "url": "", "weight": {"medium": 0, "major": 2} }, + {"name": "Rod of Metamagic, Empower, greater", "cost": 73000, "url": "", "weight": {"medium": 0, "major": 2} }, + {"name": "Rod of Metamagic, Quicken", "cost": 75500, "url": "", "weight": {"medium": 0, "major": 2} }, + {"name": "Rod of Alertness", "cost": 85000, "url": "", "weight": {"medium": 0, "major": 2} }, + {"name": "Rod of Metamagic, Maximize, greater", "cost": 121500, "url": "", "weight": {"medium": 0, "major": 1} }, + {"name": "Rod of Metamagic, Quicken, greater", "cost": 170000, "url": "", "weight": {"medium": 0, "major": 1} } + ] +} \ No newline at end of file diff --git a/sources/CRB/Spells.json b/sources/CRB/Spells.json new file mode 100644 index 0000000..f71c8fa --- /dev/null +++ b/sources/CRB/Spells.json @@ -0,0 +1,258 @@ +{ + "data": { + "Arcane": [ + ["Resistance", + "Acid Splash", "Detect Magic", "Detect Poison", "Read Magic", + "Daze", "Dancing Lights", "Flare", "Light", "Ray of Frost", + "Ghost Sound", "Bleed", "Disrupt Undead", "Touch of Fatigue", + "Mage Hand", "Mending", "Message", "Open/Close", "Arcane Mark", + "Prestidigitation"], + ["Alarm", + "Endure Elements", "Hold Portal", "Protection from Chaos", + "Protection from Evil", "Protection from Good", + "Protection from Law", "Shield", "Grease", "Mage Armor", + "Mount", "Obscuring Mist", "Summon Monster I", "Unseen Servant", + "Comprehend Languages", "Detect Secret Doors", "Detect Undead", + "Identify", "True Strike", "Charm Person", "Hypnotism", "Sleep", + "Burning Hands", "Floating Disk", "Magic Missile", + "Shocking Grasp", "Color Spray", "Disguise Self", "Magic Aura", + "Silent Image", "Ventriloquism", "Cause Fear", "Chill Touch", + "Ray of Enfeeblement", "Animate Rope", "Enlarge Person", + "Erase", "Expeditious Retreat", "Feather Fall", "Jump", + "Magic Weapon", "Reduce Person"], + ["Arcane Lock", + "Obscure Object", "Protection from Arrows", "Resist Energy", + "Acid Arrow", "Fog Cloud", "Glitterdust", "Summon Monster II", + "Summon Swarm", "Web", "Detect Thoughts", "Locate Object", + "See Invisibility", "Daze Monster", "Hideous Laughter", + "Touch of Idiocy", "Continual Flame", "Darkness", + "Flaming Sphere", "Gust of Wind", "Scorching Ray", "Shatter", + "Blur", "Hypnotic Pattern", "Invisibility", "Magic Mouth", + "Minor Image", "Mirror Image", "Misdirection", "Phantom Trap", + "Blindness/Deafness", "Command Undead", "False Life", + "Ghoul Touch", "Scare", "Spectral Hand", "Alter Self", + "Bear's Endurance", "Bull's Strength", "Cat's Grace", + "Darkvision", "Eagle's Splendor", "Fox's Cunning", "Knock", + "Levitate", "Make Whole", "Owl's Wisdom", "Pyrotechnics", + "Rope Trick", "Spider Climb", "Whispering Wind"], + ["Dispel Magic", + "Explosive Runes", "Magic Circle against Chaos", + "Magic Circle against Evil", "Magic Circle against Good", + "Magic Circle against Law", "Nondetection", + "Protection from Energy", "Phantom Steed", "Sepia Snake Sigil", + "Sleet Storm", "Stinking Cloud", "Summon Monster III", + "Arcane Sight", "Clairaudience/Clairvoyance", "Tongues", + "Deep Slumber", "Heroism", "Hold Person", "Rage", "Suggestion", + "Daylight", "Fireball", "Lightning Bolt", "Tiny Hut", + "Wind Wall", "Displacement", "Illusory Script", + "Invisibility Sphere", "Major Image", "Gentle Repose", + "Halt Undead", "Ray of Exhaustion", "Vampiric Touch", + "Beast Shape I", "Blink", "Flame Arrow", "Fly", "Gaseous Form", + "Haste", "Keen Edge", "Magic Weapon, Greater", "Secret Page", + "Shrink Item", "Slow", "Water Breathing"], + ["Dimensional Anchor", + "Fire Trap", "Globe of Invulnerability, Lesser", "Remove Curse", + "Stoneskin", "Black Tentacles", "Dimension Door", + "Minor Creation", "Secure Shelter", "Solid Fog", + "Summon Monster IV", "Arcane Eye", "Detect Scrying", + "Locate Creature", "Scrying", "Charm Monster", "Confusion", + "Crushing Despair", "Geas, Lesser", "Fire Shield", "Ice Storm", + "Resilient Sphere", "Shout", "Wall of Fire", "Wall of Ice", + "Hallucinatory Terrain", "Illusory Wall", + "Invisibility, Greater", "Phantasmal Killer", "Rainbow Pattern", + "Shadow Conjuration", "Animate Dead", "Bestow Curse", + "Contagion", "Enervation", "Fear", "Beast Shape II", + "Elemental Body I", "Enlarge Person, Mass", "Mnemonic Enhancer", + "Reduce Person, Mass", "Stone Shape"], + ["Break Enchantment", + "Dismissal", "Mage's Private Sanctum", "Cloudkill", + "Mage's Faithful Hound", "Major Creation", + "Planar Binding, Lesser", "Secret Chest", "Summon Monster V", + "Teleport", "Wall of Stone", "Contact Other Plane", + "Prying Eyes", "Telepathic Bond", "Dominate Person", + "Feeblemind", "Hold Monster", "Mind Fog", "Symbol of Sleep", + "Cone of Cold", "Interposing Hand", "Sending", "Wall of Force", + "Dream", "False Vision", "Mirage Arcana", "Nightmare", + "Persistent Image", "Seeming", "Shadow Evocation", "Blight", + "Magic Jar", "Symbol of Pain", "Waves of Fatigue", + "Animal Growth", "Baleful Polymorph", "Beast Shape III", + "Elemental Body II", "Fabricate", "Overland Flight", "Passwall", + "Plant Shape I", "Polymorph", "Telekinesis", + "Transmute Mud to Rock", "Transmute Rock to Mud", "Permanency"], + ["Antimagic Field", + "Dispel Magic, Greater", "Globe of Invulnerability", + "Guards and Wards", "Repulsion", "Acid Fog", "Planar Binding", + "Summon Monster VI", "Wall of Iron", "Analyze Dweomer", + "Legend Lore", "True Seeing", "Geas/Quest", "Heroism, Greater", + "Suggestion, Mass", "Symbol of Persuasion", "Chain Lightning", + "Contingency", "Forceful Hand", "Freezing Sphere", "Mislead", + "Permanent Image", "Programmed Image", "Shadow Walk", "Veil", + "Circle of Death", "Create Undead", "Eyebite", "Symbol of Fear", + "Undeath to Death", "Bear's Endurance, Mass", "Beast Shape IV", + "Bull's Strength, Mass", "Cat's Grace, Mass", "Control Water", + "Disintegrate", "Eagle's Splendor, Mass", "Elemental Body III", + "Flesh to Stone", "Form of the Dragon I", "Fox's Cunning, Mass", + "Mage's Lucubration", "Move Earth", "Owl's Wisdom, Mass", + "Plant Shape II", "Stone to Flesh", "Transformation"], + ["Banishment", + "Sequester", "Spell Turning", "Instant Summons", + "Mage's Magnificent Mansion", "Phase Door", "Plane Shift", + "Summon Monster VII", "Teleport, Greater", "Teleport Object", + "Arcane Sight, Greater", "Scrying, Greater", "Vision", + "Hold Person, Mass", "Insanity", "Power Word Blind", + "Symbol of Stunning", "Delayed Blast Fireball", "Forcecage", + "Grasping Hand", "Mage's Sword", "Prismatic Spray", + "Invisibility, Mass", "Project Image", + "Shadow Conjuration, Greater", "Simulacrum", "Control Undead", + "Finger of Death", "Symbol of Weakness", "Waves of Exhaustion", + "Control Weather", "Elemental Body IV", "Ethereal Jaunt", + "Form of the Dragon II", "Giant Form I", "Plant Shape III", + "Polymorph, Greater", "Reverse Gravity", "Statue", + "Limited Wish"], + ["Dimensional Lock", + "Mind Blank", "Prismatic Wall", "Protection from Spells", + "Incendiary Cloud", "Maze", "Planar Binding, Greater", + "Summon Monster VIII", "Trap the Soul", "Discern Location", + "Moment of Prescience", "Prying Eyes, Greater", "Antipathy", + "Binding", "Charm Monster, Mass", "Demand", + "Irresistible Dance", "Power Word Stun", "Symbol of Insanity", + "Sympathy", "Clenched Fist", "Polar Ray", "Shout, Greater", + "Sunburst", "Telekinetic Sphere", "Scintillating Pattern", + "Screen", "Shadow Evocation, Greater", "Clone", + "Create Greater Undead", "Horrid Wilting", "Symbol of Death", + "Form of the Dragon III", "Giant Form II", "Iron Body", + "Polymorph Any Object", "Temporal Stasis"], + ["Freedom", + "Imprisonment", "Mage's Disjunction", "Prismatic Sphere", + "Gate", "Refuge", "Summon Monster IX", "Teleportation Circle", + "Foresight", "Dominate Monster", "Hold Monster, Mass", + "Power Word Kill", "Crushing Hand", "Meteor Swarm", "Shades", + "Weird", "Astral Projection", "Energy Drain", "Soul Bind", + "Wail of the Banshee", "Etherealness", "Shapechange", + "Time Stop", "Wish"] + ], + "Divine" : [ + ["Bleed", + "Create Water", "Detect Magic", "Detect Poison", "Guidance", + "Light", "Mending", "Purify Food and Drink", "Read Magic", + "Resistance", "Stabilize", "Virtue", "Flare", "Know Direction"], + ["Bane", + "Bless", "Bless Water", "Cause Fear", "Command", + "Comprehend Languages", "Cure Light Wounds", "Curse Water", + "Deathwatch", "Detect Chaos", "Detect Evil", "Detect Good", + "Detect Law", "Detect Undead", "Divine Favor", "Doom", + "Endure Elements", "Entropic Shield", "Hide from Undead", + "Inflict Light Wounds", "Magic Stone", "Magic Weapon", + "Obscuring Mist", "Protection from Chaos", + "Protection from Evil", "Protection from Good", + "Protection from Law", "Remove Fear", "Sanctuary", + "Shield of Faith", "Summon Monster I", "Calm Animals", + "Charm Animal", "Detect Animals or Plants", + "Detect Snares and Pits", "Entangle", "Faerie Fire", + "Goodberry", "Hide from Animals", "Jump", "Longstrider", + "Magic Fang", "Pass without Trace", "Produce Flame", + "Shillelagh", "Speak with Animals", "Summon Nature's Ally I"], + ["Aid", + "Align Weapon", "Augury", "Bear's Endurance", "Bull's Strength", + "Calm Emotions", "Consecrate", "Cure Moderate Wounds", + "Darkness", "Death Knell", "Delay Poison", "Desecrate", + "Eagle's Splendor", "Enthrall", "Find Traps", "Gentle Repose", + "Hold Person", "Inflict Moderate Wounds", "Make Whole", + "Owl's Wisdom", "Remove Paralysis", "Resist Energy", + "Restoration, Lesser", "Shatter", "Shield Other", "Silence", + "Sound Burst", "Spiritual Weapon", "Status", + "Summon Monster II", "Undetectable Alignment", "Zone of Truth", + "Animal Messenger", "Animal Trance", "Barkskin", "Cat's Grace", + "Chill Metal", "Delay Poison", "Fire Trap", "Flame Blade", + "Flaming Sphere", "Fog Cloud", "Gust of Wind", "Heat Metal", + "Hold Animal", "Reduce Animal", "Soften Earth and Stone", + "Spider Climb", "Summon Nature's Ally II", "Summon Swarm", + "Tree Shape", "Warp Wood", "Wood Shape"], + ["Animate Dead", + "Bestow Curse", "Blindness/Deafness", "Contagion", + "Continual Flame", "Create Food and Water", + "Cure Serious Wounds", "Daylight", "Deeper Darkness", + "Dispel Magic", "Glyph of Warding", "Helping Hand", + "Inflict Serious Wounds", "Invisibility Purge", "Locate Object", + "Magic Circle against Chaos", "Magic Circle against Evil", + "Magic Circle against Good", "Magic Circle against Law", + "Magic Vestment", "Meld into Stone", "Obscure Object", "Prayer", + "Protection from Energy", "Remove Blindness/Deafness", + "Remove Curse", "Remove Disease", "Searing Light", + "Speak with Dead", "Stone Shape", "Summon Monster III", + "Water Breathing", "Water Walk", "Wind Wall", "Call Lightning", + "Diminish Plants", "Dominate Animal", "Magic Fang, Greater", + "Meld into Stone", "Neutralize Poison", "Plant Growth", + "Poison", "Quench", "Sleet Storm", "Snare", "Speak with Plants", + "Spike Growth", "Summon Nature's Ally III"], + ["Air Walk", + "Chaos Hammer", "Control Water", "Cure Critical Wounds", + "Death Ward", "Dimensional Anchor", "Discern Lies", "Dismissal", + "Divination", "Divine Power", "Freedom of Movement", + "Giant Vermin", "Holy Smite", "Imbue with Spell Ability", + "Inflict Critical Wounds", "Magic Weapon, Greater", + "Neutralize Poison", "Order's Wrath", "Planar Ally, Lesser", + "Poison", "Repel Vermin", "Restoration", "Sending", + "Spell Immunity", "Summon Monster IV", "Tongues", + "Unholy Blight", "Antiplant Shell", "Blight", "Command Plants", + "Flame Strike", "Freedom of Movement", "Giant Vermin", + "Ice Storm", "Reincarnate", "Repel Vermin", "Rusting Grasp", + "Scrying", "Spike Stones", "Summon Nature's Ally IV"], + ["Atonement", + "Break Enchantment", "Breath of Life", "Command, Greater", + "Commune", "Cure Light Wounds, Mass", "Dispel Chaos", + "Dispel Evil", "Dispel Good", "Dispel Law", "Disrupting Weapon", + "Flame Strike", "Hallow", "Inflict Light Wounds, Mass", + "Insect Plague", "Mark of Justice", "Plane Shift", "Raise Dead", + "Righteous Might", "Slay Living", "Spell Resistance", + "Summon Monster V", "Symbol of Pain", "Symbol of Sleep", + "True Seeing", "Unhallow", "Wall of Stone", "Animal Growth", + "Awaken", "Baleful Polymorph", "Call Lightning Storm", + "Commune with Nature", "Control Winds", "Death Ward", + "Insect Plague", "Stoneskin", "Summon Nature's Ally V", + "Transmute Mud to Rock", "Transmute Rock to Mud", "Tree Stride", + "Wall of Fire", "Wall of Thorns"], + ["Animate Objects", + "Antilife Shell", "Banishment", "Bear's Endurance, Mass", + "Blade Barrier", "Bull's Strength, Mass", "Create Undead", + "Cure Moderate Wounds, Mass", "Dispel Magic, Greater", + "Eagle's Splendor, Mass", "Find the Path", "Forbiddance", + "Geas/Quest", "Glyph of Warding, Greater", "Harm", "Heal", + "Heroes' Feast", "Inflict Moderate Wounds, Mass", + "Owl's Wisdom, Mass", "Planar Ally", "Summon Monster VI", + "Symbol of Fear", "Symbol of Persuasion", "Undeath to Death", + "Wind Walk", "Word of Recall", "Antilife Shell", + "Cat's Grace, Mass", "Fire Seeds", "Ironwood", "Liveoak", + "Move Earth", "Owl's Wisdom, Mass", "Repel Wood", "Spellstaff", + "Stone Tell", "Summon Nature's Ally VI", "Transport via Plants", + "Wall of Stone"], + ["Blasphemy", + "Control Weather", "Cure Serious Wounds, Mass", "Destruction", + "Dictum", "Ethereal Jaunt", "Holy Word", + "Inflict Serious Wounds, Mass", "Refuge", "Regenerate", + "Repulsion", "Restoration, Greater", "Resurrection", + "Scrying, Greater", "Summon Monster VII", "Symbol of Stunning", + "Symbol of Weakness", "Word of Chaos", "Animate Plants", + "Changestaff", "Control Weather", "Creeping Doom", "Fire Storm", + "Summon Nature's Ally VII", "Sunbeam", + "Transmute Metal to Wood", "True Seeing"], + ["Antimagic Field", + "Cloak of Chaos", "Create Greater Undead", + "Cure Critical Wounds, Mass", "Dimensional Lock", + "Discern Location", "Earthquake", "Fire Storm", "Holy Aura", + "Inflict Critical Wounds, Mass", "Planar Ally, Greater", + "Shield of Law", "Spell Immunity, Greater", + "Summon Monster VIII", "Symbol of Death", "Symbol of Insanity", + "Unholy Aura", "Animal Shapes", "Control Plants", + "Finger of Death", "Repel Metal or Stone", "Reverse Gravity", + "Summon Nature's Ally VIII", "Sunburst", "Whirlwind", + "Word of Recall"], + ["Astral Projection", + "Energy Drain", "Etherealness", "Gate", "Heal, Mass", + "Implosion", "Miracle", "Soul Bind", "Storm of Vengeance", + "Summon Monster IX", "True Resurrection", "Antipathy", + "Elemental Swarm", "Foresight", "Regenerate", "Shambler", + "Shapechange", "Summon Nature's Ally IX", "Sympathy"] + ] + } +} \ No newline at end of file diff --git a/sources/CRB/Wondrous Items.json b/sources/CRB/Wondrous Items.json new file mode 100644 index 0000000..0e1a33d --- /dev/null +++ b/sources/CRB/Wondrous Items.json @@ -0,0 +1,396 @@ +{ + "data": { + "minor": [ + { "name" : "Feather token, anchor", "cost" : 50, "url" : "#feather-token" }, + { "name" : "Universal solvent", "cost" : 50, "url" : "" }, + { "name" : "Elixir of love", "cost" : 150, "url" : "" }, + { "name" : "Unguent of timelessness", "cost" : 150, "url" : "" }, + { "name" : "Feather token, fan", "cost" : 200, "url" : "" }, + { "name" : "Dust of tracelessness", "cost" : 250, "url" : "" }, + { "name" : "Elixir of hiding", "cost" : 250, "url" : "" }, + { "name" : "Elixir of tumbling", "cost" : 250, "url" : "" }, + { "name" : "Elixir of swimming", "cost" : 250, "url" : "" }, + { "name" : "Elixir of vision", "cost" : 250, "url" : "" }, + { "name" : "Silversheen", "cost" : 250, "url" : "" }, + { "name" : "Feather token, bird", "cost" : 300, "url" : "" }, + { "name" : "Feather token, tree", "cost" : 400, "url" : "" }, + { "name" : "Feather token, swan boat", "cost" : 450, "url" : "" }, + { "name" : "Elixir of truth", "cost" : 500, "url" : "" }, + { "name" : "Feather token, whip", "cost" : 500, "url" : "" }, + { "name" : "Dust of dryness", "cost" : 850, "url" : "" }, + { "name" : "Hand of the mage", "cost" : 900, "url" : "" }, + { "name" : "Bracers of armor +1", "cost" : 1000, "url" : "" }, + { "name" : "Cloak of resistance +1", "cost" : 1000, "url" : "" }, + { "name" : "Pearl of power, 1st-level spell", "cost" : 1000, + "url" : "" }, + { "name" : "Phylactery of faithfulness", "cost" : 1000, "url" : "" }, + { "name" : "Salve of slipperiness", "cost" : 1000, "url" : "" }, + { "name" : "Elixir of fire breath", "cost" : 1100, "url" : "" }, + { "name" : "Pipes of the sewers", "cost" : 1150, "url" : "" }, + { "name" : "Dust of illusion", "cost" : 1200, "url" : "" }, + { "name" : "Brooch of shielding", "cost" : 1500, "url" : "" }, + { "name" : "Necklace of fireballs type I", "cost" : 1650, "url" : "" }, + { "name" : "Dust of appearance", "cost" : 1800, "url" : "" }, + { "name" : "Hat of disguise", "cost" : 1800, "url" : "" }, + { "name" : "Pipes of sounding", "cost" : 1800, "url" : "" }, + { "name" : "Efficient quiver", "cost" : 1800, "url" : "" }, + { "name" : "Amulet of natural armor +1", "cost" : 2000, "url" : "" }, + { "name" : "Handy haversack", "cost" : 2000, "url" : "" }, + { "name" : "Horn of fog", "cost" : 2000, "url" : "" }, + { "name" : "Elemental gem", "cost" : 2250, "url" : "" }, + { "name" : "Robe of bones", "cost" : 2400, "url" : "" }, + { "name" : "Sovereign glue", "cost" : 2400, "url" : "" }, + { "name" : "Bag of holding type I", "cost" : 2500, "url" : "" }, + { "name" : "Boots of elvenkind", "cost" : 2500, "url" : "" }, + { "name" : "Boots of the winterlands", "cost" : 2500, "url" : "" }, + { "name" : "Candle of truth", "cost" : 2500, "url" : "" }, + { "name" : "Cloak of elvenkind", "cost" : 2500, "url" : "" }, + { "name" : "Eyes of the eagle", "cost" : 2500, "url" : "" }, + { "name" : "Goggles of minute seeing", "cost" : 2500, "url" : "" }, + { "name" : "Scarab, golembane", "cost" : 2500, "url" : "" }, + { "name" : "Necklace of fireballs type II", "cost" : 2700, "url" : "" }, + { "name" : "Stone of alarm", "cost" : 2700, "url" : "" }, + { "name" : "Bead of force", "cost" : 3000, "url" : "" }, + { "name" : "Chime of opening", "cost" : 3000, "url" : "" }, + { "name" : "Horseshoes of speed", "cost" : 3000, "url" : "" }, + { "name" : "Rope of climbing", "cost" : 3000, "url" : "" }, + { "name" : "Bag of tricks, gray", "cost" : 3400, "url" : "" }, + { "name" : "Dust of disappearance", "cost" : 3500, "url" : "" }, + { "name" : "Lens of detection", "cost" : 3500, "url" : "" }, + { "name" : "Druid's Vestment", "cost" : 3750, "url" : "" }, + { "name" : "Figurine of wondrous power, silver raven", "cost" : 3800, + "url" : "" }, + { "name" : "Belt of giant strength +2", "cost" : 4000, "url" : "" }, + { "name" : "Belt of incredible dexterity +2", "cost" : 4000, + "url" : "" }, + { "name" : "Belt of mighty constitution +2", "cost" : 4000, + "url" : "" }, + { "name" : "Bracers of armor +2", "cost" : 4000, "url" : "" }, + { "name" : "Cloak of resistance +2", "cost" : 4000, "url" : "" }, + { "name" : "Gloves of arrow snaring", "cost" : 4000, "url" : "" }, + { "name" : "Headband of alluring charisma +2", "cost" : 4000, + "url" : "" }, + { "name" : "Headband of inspired wisdom +2", "cost" : 4000, + "url" : "" }, + { "name" : "Headband of vast intelligence +2", "cost" : 4000, + "url" : "" }, + { "name" : "Ioun stone, clear spindle", "cost" : 4000, "url" : "" }, + { "name" : "Restorative ointment", "cost" : 4000, "url" : "" }, + { "name" : "Marvelous pigments", "cost" : 4000, "url" : "" }, + { "name" : "Pearl of power, 2nd-level spell", "cost" : 4000, + "url" : "" }, + { "name" : "Stone salve", "cost" : 4000, "url" : "" }, + { "name" : "Necklace of fireballs type III", "cost" : 4350, + "url" : "" }, + { "name" : "Circlet of persuasion", "cost" : 4500, "url" : "" }, + { "name" : "Slippers of spider climbing", "cost" : 4800, "url" : "" }, + { "name" : "Incense of meditation", "cost" : 4900, "url" : "" }, + { "name" : "Amulet of mighty fists +1", "cost" : 5000, "url" : "" }, + { "name" : "Bag of holding type II", "cost" : 5000, "url" : "" }, + { "name" : "Bracers of archery, lesser", "cost" : 5000, "url" : "" }, + { "name" : "Ioun stone, dusty rose prism", "cost" : 5000, "url" : "" }, + { "name" : "Helm of comprehend languages and read magic", "cost" : 5200, + "url" : "" }, + { "name" : "Vest of escape", "cost" : 5200, "url" : "" }, + { "name" : "Eversmoking bottle", "cost" : 5400, "url" : "" }, + { "name" : "Sustaining spoon", "cost" : 5400, "url" : "" }, + { "name" : "Necklace of fireballs type IV", "cost" : 5400, "url" : "" }, + { "name" : "Boots of striding and springing", "cost" : 5500, + "url" : "" }, + { "name" : "Wind fan", "cost" : 5500, "url" : "" }, + { "name" : "Necklace of fireballs type V", "cost" : 5850, "url" : "" }, + { "name" : "Horseshoes of a zephyr", "cost" : 6000, "url" : "" }, + { "name" : "Pipes of haunting", "cost" : 6000, "url" : "" }, + { "name" : "Gloves of swimming and climbing", "cost" : 6250, + "url" : "" }, + { "name" : "Crown of blasting, minor", "cost" : 6480, "url" : "" }, + { "name" : "Horn of goodness/evil", "cost" : 6500, "url" : "" }, + { "name" : "Robe of useful items", "cost" : 7000, "url" : "" }, + { "name" : "Boat, folding", "cost" : 7200, "url" : "" }, + { "name" : "Cloak of the manta ray", "cost" : 7200, "url" : "" }, + { "name" : "Bottle of air", "cost" : 7250, "url" : "" }, + { "name" : "Bag of holding type III", "cost" : 7400, "url" : "" }, + { "name" : "Periapt of health", "cost" : 7400, "url" : "" }, + { "name" : "Boots of levitation", "cost" : 7500, "url" : "" }, + { "name" : "Harp of charming", "cost" : 750, "url" : "" } + ], + "medium" : [ + { "name" : "Amulet of natural armor +2", "cost" : 8000, + "url" : "#amulet-of-natural-armor" }, + { "name" : "Golem manual, flesh", "cost" : 8000, "url" : "" }, + { "name" : "Hand of glory", "cost" : 8000, "url" : "" }, + { "name" : "Ioun stone, deep red sphere", "cost" : 8000, "url" : "" }, + { "name" : "Ioun stone, incandescent blue sphere", "cost" : 8000, + "url" : "" }, + { "name" : "Ioun stone, pale blue rhomboid", "cost" : 8000, + "url" : "" }, + { "name" : "Ioun stone, pink and green sphere", "cost" : 8000, + "url" : "" }, + { "name" : "Ioun stone, pink rhomboid", "cost" : 8000, "url" : "" }, + { "name" : "Ioun stone, scarlet and blue sphere", "cost" : 8000, + "url" : "" }, + { "name" : "Deck of illusions", "cost" : 8100, "url" : "" }, + { "name" : "Necklace of fireballs type VI", "cost" : 8100, "url" : "" }, + { "name" : "Candle of invocation", "cost" : 8400, "url" : "" }, + { "name" : "Robe of blending", "cost" : 8400, "url" : "" }, + { "name" : "Bag of tricks, rust", "cost" : 8500, "url" : "" }, + { "name" : "Necklace of fireballs type VII", "cost" : 8700, + "url" : "" }, + { "name" : "Bracers of armor +3", "cost" : 9000, "url" : "" }, + { "name" : "Cloak of resistance +3", "cost" : 9000, "url" : "" }, + { "name" : "Decanter of endless water", "cost" : 9000, "url" : "" }, + { "name" : "Necklace of adaptation", "cost" : 9000, "url" : "" }, + { "name" : "Pearl of power, 3rd-level spell", "cost" : 9000, + "url" : "" }, + { "name" : "Figurine of wondrous power, serpentine owl", "cost" : 9100, + "url" : "" }, + { "name" : "Strand of prayer beads, lesser", "cost" : 9600, + "url" : "" }, + { "name" : "Bag of holding type IV", "cost" : 10000, "url" : "" }, + { "name" : "Belt of physical might +2", "cost" : 10000, "url" : "" }, + { "name" : "Figurine of wondrous power, bronze griffon", "cost" : 10000, + "url" : "" }, + { "name" : "Figurine of wondrous power, ebony fly", "cost" : 10000, + "url" : "" }, + { "name" : "Glove of storing", "cost" : 10000, "url" : "" }, + { "name" : "Headband of mental prowess +2", "cost" : 10000, + "url" : "" }, + { "name" : "Ioun stone, dark blue rhomboid", "cost" : 10000, + "url" : "" }, + { "name" : "Cape of the mountebank", "cost" : 10080, "url" : "" }, + { "name" : "Phylactery of negative channeling", "cost" : 11000, + "url" : "" }, + { "name" : "Phylactery of positive channeling", "cost" : 11000, + "url" : "" }, + { "name" : "Gauntlet of rust", "cost" : 11500, "url" : "" }, + { "name" : "Boots of speed", "cost" : 12000, "url" : "" }, + { "name" : "Goggles of night", "cost" : 12000, "url" : "" }, + { "name" : "Golem manual, clay", "cost" : 12000, "url" : "" }, + { "name" : "Medallion of thoughts", "cost" : 12000, "url" : "" }, + { "name" : "Blessed book", "cost" : 12500, "url" : "" }, + { "name" : "Gem of brightness", "cost" : 13000, "url" : "" }, + { "name" : "Lyre of building", "cost" : 13000, "url" : "" }, + { "name" : "Monk's Robe", "cost" : 13000, "url" : "" }, + { "name" : "Cloak of arachnida", "cost" : 14000, "url" : "" }, + { "name" : "Belt of dwarvenkind", "cost" : 14900, "url" : "" }, + { "name" : "Periapt of wound closure", "cost" : 15000, "url" : "" }, + { "name" : "Pearl of the sirines", "cost" : 15300, "url" : "" }, + { "name" : "Figurine of wondrous power, onyx dog", "cost" : 15500, + "url" : "" }, + { "name" : "Bag of tricks, tan", "cost" : 16000, "url" : "" }, + { "name" : "Belt of giant strength +4", "cost" : 16000, "url" : "" }, + { "name" : "Belt of incredible dexterity +4", "cost" : 16000, + "url" : "" }, + { "name" : "Belt of mighty constitution +4", "cost" : 16000, + "url" : "" }, + { "name" : "Belt of physical perfection +2", "cost" : 16000, + "url" : "" }, + { "name" : "Boots, winged", "cost" : 16000, "url" : "" }, + { "name" : "Bracers of armor +4", "cost" : 16000, "url" : "" }, + { "name" : "Cloak of resistance +4", "cost" : 16000, "url" : "" }, + { "name" : "Headband of alluring charisma +4", "cost" : 16000, + "url" : "" }, + { "name" : "Headband of inspired wisdom +4", "cost" : 16000, + "url" : "" }, + { "name" : "Headband of mental superiority +2", "cost" : 16000, + "url" : "" }, + { "name" : "Headband of vast intelligence +4", "cost" : 16000, + "url" : "" }, + { "name" : "Pearl of power, 4th-level spell", "cost" : 16000, + "url" : "" }, + { "name" : "Scabbard of keen edges", "cost" : 16000, "url" : "" }, + { "name" : "Figurine of wondrous power, golden lions", "cost" : 16500, + "url" : "" }, + { "name" : "Chime of interruption", "cost" : 16800, "url" : "" }, + { "name" : "Broom of flying", "cost" : 17000, "url" : "" }, + { "name" : "Figurine of wondrous power, marble elephant", + "cost" : 17000, "url" : "" }, + { "name" : "Amulet of natural armor +3", "cost" : 18000, "url" : "" }, + { "name" : "Ioun stone, iridescent spindle", "cost" : 18000, + "url" : "" }, + { "name" : "Bracelet of friends", "cost" : 19000, "url" : "" }, + { "name" : "Amulet of mighty fists +2", "cost" : 20000, "url" : "" }, + { "name" : "Carpet of flying, 5 ft. by 5 ft.", "cost" : 20000, + "url" : "" }, + { "name" : "Horn of blasting", "cost" : 20000, "url" : "" }, + { "name" : "Ioun stone, pale lavender ellipsoid", "cost" : 20000, + "url" : "" }, + { "name" : "Ioun stone, pearly white spindle", "cost" : 20000, + "url" : "" }, + { "name" : "Portable hole", "cost" : 20000, "url" : "" }, + { "name" : "Stone of good luck (luckstone)", "cost" : 20000, + "url" : "" }, + { "name" : "Figurine of wondrous power, ivory goats", "cost" : 21000, + "url" : "" }, + { "name" : "Rope of entanglement", "cost" : 21000, "url" : "" }, + { "name" : "Golem manual, stone", "cost" : 22000, "url" : "" }, + { "name" : "Mask of the skull", "cost" : 22000, "url" : "" }, + { "name" : "Mattock of the titans", "cost" : 23348, "url" : "" }, + { "name" : "Crown of blasting, major", "cost" : 23760, "url" : "" }, + { "name" : "Cloak of displacement, minor", "cost" : 24000, "url" : "" }, + { "name" : "Helm of underwater action", "cost" : 24000, "url" : "" }, + { "name" : "Bracers of archery, greater", "cost" : 25000, "url" : "" }, + { "name" : "Bracers of armor +5", "cost" : 25000, "url" : "" }, + { "name" : "Cloak of resistance +5", "cost" : 25000, "url" : "" }, + { "name" : "Eyes of doom", "cost" : 25000, "url" : "" }, + { "name" : "Pearl of power, 5th-level spell", "cost" : 25000, + "url" : "" }, + { "name" : "Maul of the titans", "cost" : 25305, "url" : "" }, + { "name" : "Cloak of the bat", "cost" : 26000, "url" : "" }, + { "name" : "Iron bands of binding", "cost" : 26000, "url" : "" }, + { "name" : "Cube of frost resistance", "cost" : 27000, "url" : "" }, + { "name" : "Helm of telepathy", "cost" : 27000, "url" : "" }, + { "name" : "Periapt of proof against poison", "cost" : 27000, + "url" : "" }, + { "name" : "Robe of scintillating colors", "cost" : 27000, "url" : "" }, + { "name" : "Manual of bodily health +1", "cost" : 27500, "url" : "" }, + { "name" : "Manual of gainful exercise +1", "cost" : 27500, + "url" : "" }, + { "name" : "Manual of quickness in action +1", "cost" : 27500, + "url" : "" }, + { "name" : "Tome of clear thought +1", "cost" : 27500, "url" : "" }, + { "name" : "Tome of leadership and influence +1", "cost" : 27500, + "url" : "" }, + { "name" : "Tome of understanding +1", "cost" : 2750, "url" : "" }], + "major": [ + { "name" : "Dimensional shackles", "cost" : 28000, + "url" : "#dimensional-shackles" }, + { "name" : "Figurine of wondrous power, obsidian steed", "cost" : 28500, + "url" : "" }, + { "name" : "Drums of panic", "cost" : 30000, "url" : "" }, + { "name" : "Ioun stone, orange prism", "cost" : 30000, "url" : "" }, + { "name" : "Ioun stone, pale green prism", "cost" : 30000, "url" : "" }, + { "name" : "Lantern of revealing", "cost" : 30000, "url" : "" }, + { "name" : "Amulet of natural armor +4", "cost" : 32000, "url" : "" }, + { "name" : "Amulet of proof against detection and location", + "cost" : 35000, "url" : "" }, + { "name" : "Carpet of flying, 5 ft. by 10 ft.", "cost" : 35000, + "url" : "" }, + { "name" : "Golem manual, iron", "cost" : 35000, "url" : "" }, + { "name" : "Belt of giant strength +6", "cost" : 36000, "url" : "" }, + { "name" : "Belt of incredible dexterity +6", "cost" : 36000, + "url" : "" }, + { "name" : "Belt of mighty constitution +6", "cost" : 36000, + "url" : "" }, + { "name" : "Bracers of armor +6", "cost" : 36000, "url" : "" }, + { "name" : "Headband of alluring charisma +6", "cost" : 36000, + "url" : "" }, + { "name" : "Headband of inspired wisdom +6", "cost" : 36000, + "url" : "" }, + { "name" : "Headband of vast intelligence +6", "cost" : 36000, + "url" : "" }, + { "name" : "Ioun stone, vibrant purple prism", "cost" : 36000, + "url" : "" }, + { "name" : "Pearl of power, 6th-level spell", "cost" : 36000, + "url" : "" }, + { "name" : "Scarab of protection", "cost" : 38000, "url" : "" }, + { "name" : "Belt of physical might +4", "cost" : 40000, "url" : "" }, + { "name" : "Headband of mental prowess +4", "cost" : 40000, + "url" : "" }, + { "name" : "Ioun stone, lavender and green ellipsoid", "cost" : 40000, + "url" : "" }, + { "name" : "Ring gates", "cost" : 40000, "url" : "" }, + { "name" : "Crystal ball", "cost" : 42000, "url" : "" }, + { "name" : "Golem manual, stone guardian", "cost" : 44000, "url" : "" }, + { "name" : "Amulet of mighty fists +3", "cost" : 45000, "url" : "" }, + { "name" : "Strand of prayer beads", "cost" : 45800, "url" : "" }, + { "name" : "Orb of storms", "cost" : 48000, "url" : "" }, + { "name" : "Boots of teleportation", "cost" : 49000, "url" : "" }, + { "name" : "Bracers of armor +7", "cost" : 49000, "url" : "" }, + { "name" : "Pearl of power, 7th-level spell", "cost" : 49000, + "url" : "" }, + { "name" : "Amulet of natural armor +5", "cost" : 50000, "url" : "" }, + { "name" : "Cloak of displacement, major", "cost" : 50000, "url" : "" }, + { "name" : "Crystal ball with see invisibility", "cost" : 50000, + "url" : "" }, + { "name" : "Horn of Valhalla", "cost" : 50000, "url" : "" }, + { "name" : "Crystal ball with detect thoughts", "cost" : 51000, + "url" : "" }, + { "name" : "Wings of flying", "cost" : 54000, "url" : "" }, + { "name" : "Cloak of etherealness", "cost" : 55000, "url" : "" }, + { "name" : "Instant fortress", "cost" : 55000, "url" : "" }, + { "name" : "Manual of bodily health +2", "cost" : 55000, "url" : "" }, + { "name" : "Manual of gainful exercise +2", "cost" : 55000, + "url" : "" }, + { "name" : "Manual of quickness in action +2", "cost" : 55000, + "url" : "" }, + { "name" : "Tome of clear thought +2", "cost" : 55000, "url" : "" }, + { "name" : "Tome of leadership and influence +2", "cost" : 55000, + "url" : "" }, + { "name" : "Tome of understanding +2", "cost" : 55000, "url" : "" }, + { "name" : "Eyes of charming", "cost" : 56000, "url" : "" }, + { "name" : "Robe of stars", "cost" : 58000, "url" : "" }, + { "name" : "Carpet of flying, 10 ft. by 10 ft.", "cost" : 60000, + "url" : "" }, + { "name" : "Darkskull", "cost" : 60000, "url" : "" }, + { "name" : "Cube of force", "cost" : 62000, "url" : "" }, + { "name" : "Belt of physical perfection +4", "cost" : 64000, + "url" : "" }, + { "name" : "Bracers of armor +8", "cost" : 64000, "url" : "" }, + { "name" : "Headband of mental superiority +4", "cost" : 64000, + "url" : "" }, + { "name" : "Pearl of power, 8th-level spell", "cost" : 64000, + "url" : "" }, + { "name" : "Crystal ball with telepathy", "cost" : 70000, "url" : "" }, + { "name" : "Horn of blasting, greater", "cost" : 70000, "url" : "" }, + { "name" : "Pearl of power, two spells", "cost" : 70000, "url" : "" }, + { "name" : "Helm of teleportation", "cost" : 73500, "url" : "" }, + { "name" : "Gem of seeing", "cost" : 75000, "url" : "" }, + { "name" : "Robe of the archmagi", "cost" : 75000, "url" : "" }, + { "name" : "Mantle of faith", "cost" : 76000, "url" : "" }, + { "name" : "Amulet of mighty fists +4", "cost" : 80000, "url" : "" }, + { "name" : "Crystal ball with true seeing", "cost" : 80000, + "url" : "" }, + { "name" : "Pearl of power, 9th-level spell", "cost" : 81000, + "url" : "" }, + { "name" : "Well of many worlds", "cost" : 82000, "url" : "" }, + { "name" : "Manual of bodily health +3", "cost" : 82500, "url" : "" }, + { "name" : "Manual of gainful exercise +3", "cost" : 82500, + "url" : "" }, + { "name" : "Manual of quickness in action +3", "cost" : 82500, + "url" : "" }, + { "name" : "Tome of clear thought +3", "cost" : 82500, "url" : "" }, + { "name" : "Tome of leadership and influence +3", "cost" : 82500, + "url" : "" }, + { "name" : "Tome of understanding +3", "cost" : 82500, "url" : "" }, + { "name" : "Apparatus of the crab", "cost" : 90000, "url" : "" }, + { "name" : "Belt of physical might +6", "cost" : 90000, "url" : "" }, + { "name" : "Headband of mental prowess +6", "cost" : 90000, + "url" : "" }, + { "name" : "Mantle of spell resistance", "cost" : 90000, "url" : "" }, + { "name" : "Mirror of opposition", "cost" : 92000, "url" : "" }, + { "name" : "Strand of prayer beads, greater", "cost" : 95800, + "url" : "" }, + { "name" : "Manual of bodily health +4", "cost" : 110000, "url" : "" }, + { "name" : "Manual of gainful exercise +4", "cost" : 110000, + "url" : "" }, + { "name" : "Manual of quickness in action +4", "cost" : 110000, + "url" : "" }, + { "name" : "Tome of clear thought +4", "cost" : 110000, "url" : "" }, + { "name" : "Tome of leadership and influence +4", "cost" : 110000, + "url" : "" }, + { "name" : "Tome of understanding +4", "cost" : 110000, "url" : "" }, + { "name" : "Amulet of the planes", "cost" : 120000, "url" : "" }, + { "name" : "Robe of eyes", "cost" : 120000, "url" : "" }, + { "name" : "Amulet of mighty fists +5", "cost" : 125000, "url" : "" }, + { "name" : "Helm of Brilliance", "cost" : 125000, "url" : "" }, + { "name" : "Manual of bodily health +5", "cost" : 137500, "url" : "" }, + { "name" : "Manual of gainful exercise +5", "cost" : 137500, + "url" : "" }, + { "name" : "Manual of quickness in action +5", "cost" : 137500, + "url" : "" }, + { "name" : "Tome of clear thought +5", "cost" : 137500, "url" : "" }, + { "name" : "Tome of leadership and influence +5", "cost" : 137500, + "url" : "" }, + { "name" : "Tome of understanding +5", "cost" : 137500, "url" : "" }, + { "name" : "Belt of physical perfection +6", "cost" : 144000, + "url" : "" }, + { "name" : "Headband of mental superiority +6", "cost" : 144000, + "url" : "" }, + { "name" : "Efreeti bottle", "cost" : 145000, "url" : "" }, + { "name" : "Cubic gate", "cost" : 164000, "url" : "" }, + { "name" : "Iron flask", "cost" : 170000, "url" : "" }, + { "name" : "Mirror of life trapping", "cost" : 20000, "url" : "" } + ] + } +} \ No newline at end of file diff --git a/sources/UM.json b/sources/UM.json new file mode 100644 index 0000000..40291b1 --- /dev/null +++ b/sources/UM.json @@ -0,0 +1,5 @@ +{ + "name": "Ultimate Magic", + "shortName": "UM", + "types": ["Spells"] +} \ No newline at end of file diff --git a/sources/UM/Spells.json b/sources/UM/Spells.json new file mode 100644 index 0000000..add2ec6 --- /dev/null +++ b/sources/UM/Spells.json @@ -0,0 +1,28 @@ +{ + "data": { + "Arcane": [ + [], + ["Anticipate Peril", "Chord of Shards", "Delusional Pride", "Ear-Piercing Scream", "Forced Quiet", "Fumbletongue", "Horn of Pursuit", "Ki Arrow", "Play Instrument", "Summon Minor Monster", "Unnatural Lust", "Unprepared Combatant", "Vocal Alteration", "Youthful Appearance", "Corrosive Touch", "Frostbite", "Bungle", "Decompose Corpse", "Icicle Dagger", "Interrogation", "Polypurpose Panacea", "Ray of Sickening", "Restore Corpse", "Shadow Weapon", "Snapdragon Fireworks", "Diagnose Disease", "Hex Ward", "Remove Sickness", "Sanctify Corpse"], + ["Acute Senses", "Allegro", "Boiling Blood", "Compassionate Ally", "Delay Pain", "Disguise Other", "Distracting Cacophony", "Distressing Tone", "Ghostly Disguise", "Haunting Mists", "Mad Hallucination", "Masterwork Transformation", "Miserable Pity", "Oppressive Boredom", "Piercing Shriek", "Reckless Infatuation", "Share Memory", "Silk to Steel", "Snapdragon Fireworks", "Steal Voice", "Unadulterated Loathing", "Wartrain Mount", "Blood Transcription", "Defensive Shock", "Frigid Touch", "Badger's Ferocity", "Cushioning Bands", "Disfiguring Touch ", "Pernicious Poison", "Protective Penumbra", "Sculpt Simulacrum", "Silk To Steel", "Skinsend", "Symbol of Mirroring", "Unnatural Lust", "Unshakable Chill", "Web Shelter", "Restore Eidolon, Lesser"], + ["Control Summoned Creature", "Curse of Disgust", "Exquisite Accompaniment", "Rain of Frogs", "Haunting Choir", "Mad Monkeys", "Malicious Spite", "Overwhelming Grief", "Smug Narcissism", "Terrible Remorse", "Vision of Hell", "Witness", "Force Hook Charge", "Force Punch", "Monstrous Physique I", "Undead Anatomy I", "Animate Dead, Lesser", "Anthropomorphic Animal", "Ash Storm", "Burrow", "Countless Eyes", "Distracting Cacophony", "Eldritch Fever", "Eruptive Pustules", "Excruciating Deformation", "Howling Agony", "Ki Leech", "Loathsome Veil", "Marionette Possession", "Reckless Infatuation", "Sands of Time", "Strangling Hair", "Toxic Gift", "Unadulterated Loathing", "Agonize", "Restore Eidolon", "Cackling Skull", "Spit Venom", "Vermin Shape I"], + ["Dance of a Hundred Cuts", "Daze, Mass", "Echolocation", "Envious Urge", "Primal Scream", "Serenity", "Shadow Step", "Sonic Thrust", "Utter Contempt", "Virtuoso Performance", "Wall of Sound", "Arcana Theft", "Monstrous Physique II", "Vermin Shape I", "Age Resistance, Lesser", "Agonize", "Control Summoned Creature", "Curse of Magic Negation", "Darkvision, Greater", "False Life, Greater", "Familiar Melding", "Fleshworm Infestation", "Malfunction", "Malicious Spite", "Overwhelming Grief", "Ride the Waves", "Simulacrum, Lesser", "Symbol of Revelation", "Symbol of Slowing", "Terrible Remorse", "Touch of Slime", "Vitriolic Mist", "Volcanic Storm", "Cape of Wasps", "Symbol of Healing", "Vermin Shape II"], + ["Joyful Rapture", "Ki Shout", "Resonating Word", "Shadowbard", "Vengeful Outrage", "Acidic Spray", "Corrosive Consumption", "Monstrous Physique III", "Undead Anatomy II", "Vermin Shape II", "Astral Projection, Lesser", "Curse of Disgust", "Echolocation", "Fickle Winds", "Icy Prison", "Lightning Arc", "Plague Carrier", "Possess Object", "Rapid Repair", "Smug Narcissism", "Sonic Thrust", "Soothe Construct", "Symbol of Scrying", "Unbreakable Construct", "Wall of Sound", "Conjure Black Pudding", "Create Demiplane, Lesser", "Ice Crystal Teleport", "Contagion, Greater", "Curse, Major"], + ["Dance of a Thousand Cuts", "Overwhelming Presence", "Waves of Ecstasy", "Monstrous Physique IV", "Undead Anatomy III", "Age Resistance", "Battlemind Link", "Cold Ice Strike", "Conjure Black Pudding", "Contagion, Greater", "Curse, Major", "Envious Urge", "Ice Crystal Teleport", "Leashed Shackles ", "Serenity", "Symbol of Sealing", "Utter Contempt", "Vengeful Outrage", "Create Demiplane", "Eagle Aerie", "Epidemic", "Plague Storm"], + ["Age Resistance, Greater", "Caustic Eruption", "Circle of Clarity", "Control Construct", "Create Demiplane, Lesser", "Epidemic", "Ice Body", "Joyful Rapture", "Ki Shout", "Lunar Veil", "Plague Storm", "Resonating Word", "Scouring Winds", "Temporary Resurrection", "Waves of Ecstasy", "Waves of Ecstasy"], + ["Call Construct", "Create Demiplane", "Orb of the Void", "Prediction of Failure", "Undead Anatomy IV"], + ["Create Demiplane, Greater", "Cursed Earth", "Icy Prison, Mass", "Interplanetary Teleport", "Overwhelming Presence", "Ride the Lightning", "Symbol of Strife", "Symbol of Vulnerability", "Transmute Blood to Acid", "Wooden Phalanx", "Polar Midnight"] + ], + "Divine": [ + [], + ["Decompose Corpse", "Diagnose Disease", "Forbid Action", "Know the Enemy", "Murderous Command", "Ray of Sickening", "Remove Sickness", "Restore Corpse", "Sanctify Corpse", "Summon Minor Monster", "Frostbite", "Summon Minor Ally", "Ear-Piercing Scream", "Forced Quiet", "Hex Ward", "Horn of Pursuit", "Interrogation", "Lend Judgment", "Persuasive Goad", "Vocal Alteration", "Wartrain Mount", "Wartrain Mount", "Word of Resolve", "Anticipate Peril"], + ["Animate Dead, Lesser", "Arrow of Law", "Boiling Blood", "Compassionate Ally", "Delay Pain", "Disfiguring Touch", "Dread Bolt", "Imbue with Aura", "Masterwork Transformation", "Protective Penumbra", "Shard of Chaos", "Spear of Purity", "Surmount Affliction", "Web Shelter", "Frigid Touch", "Pernicious Poison", "Tar Ball", "Unshakable Chill", "Wartrain Mount", "Acute Senses", "Disguise Other", "Distressing Tone", "Ghostly Disguise", "Howling Agony", "Holy Shield", "Vestment of the Champion", "Badger's Ferocity"], + ["Agonize", "Archon's Aura", "Badger's Ferocity", "Blessing of the Mole", "Ki Leech", "Sands of Time", "Symbol of Healing", "Vision of Hell", "Anthropomorphic Animal", "Ash Storm", "Burrow", "Burst of Nettles", "Fungal Infestation", "Mad Monkeys", "Rain of Frogs", "Spit Venom", "Vermin Shape I", "Countless Eyes", "Eldritch Fever", "Terrible Remorse", "Witness", "Blade of Bright Victory", "Fickle Winds"], + ["Aura of Doom", "Blood Crow Strike", "Control Summoned Creature", "Fleshworm Infestation", "Oracle's Vessel", "Plague Carrier", "Ride the Waves", "Soothe Construct", "Spit Venom", "Symbol of Revelation", "Symbol of Slowing", "Terrible Remorse", "Age Resistance, Lesser", "Arboreal Hammer", "Atavism", "Cape of Wasps", "Echolocation", "Touch of Slime", "Vermin Shape II", "Volcanic Storm", "Battlemind Link", "Curse of Magic Negation", "Daze, Mass", "Interrogation, Greater", "Leashed Shackles ", "Reprobation", "Bestow Grace of the Champion", "Raise Animal Companion", "Symbol of Healing", "Darkvision, Greater"], + ["Astral Projection, Lesser", "Contagion, Greater", "Curse of Magic Negation", "Curse, Major", "Fickle Winds", "Forbid Action, Greater", "Holy Ice", "Rapid Repair", "Reprobation", "Serenity", "Symbol of Scrying", "Unholy Ice", "Raise Animal Companion", "Divine Pursuit", "Lend Greater Judgment"], + ["Cold Ice Strike", "Epidemic", "Joyful Rapture", "Plague Storm", "Symbol of Sealing", "Age Resistance", "Eagle Aerie", "Overwhelming Presence"], + ["Bestow Grace of the Champion", "Circle of Clarity", "Create Demiplane, Lesser", "Lunar Veil", "Waves of Ecstasy", "Call Construct", "Create Demiplane", "Orb of the Void", "Age Resistance, Greater", "Scouring Winds"], + ["Atavism, Mass", "Blood Mist"], + ["Create Demiplane, Greater", "Cursed Earth", "Interplanetary Teleport", "Overwhelming Presence", "Polar Midnight", "Symbol of Strife", "Symbol of Vulnerability", "Wooden Phalanx", "Summon Elder Worm", "Summon Froghemoth"] + ] + } +} \ No newline at end of file diff --git a/sources/sources.json b/sources/sources.json new file mode 100644 index 0000000..0c527b0 --- /dev/null +++ b/sources/sources.json @@ -0,0 +1,3 @@ +{ + "sources": ["CRB.json", "APG.json", "UM.json"] +} \ No newline at end of file