Added more sources info, item/weapon intelligence, and stuff

This commit is contained in:
Russell Champoux committed 2015-03-16 16:18:46 -04:00
1 parent 4adddec3a6
commit 6a2f87e751
19 files changed
+684 -804

No files matched your search

-188
View File
@@ -1,188 +0,0 @@
/*global _:false */
/*global Grimoire:true */
'use strict';
//TODO: Program the "Roll twice" logic
var Armors = {};
Armors.specificBaseUrl = 'http://paizo.com/pathfinderRPG/prd/magicItems/armor.html';
Armors.getSpecifics = function() {
return [
{'name': 'Mithral shirt', 'bonus': 0, 'cost': 1100, 'url': '#mithril-shirt'},
{'name': 'Dragonhide plate', 'bonus': 0, 'cost': 3300, 'url':''},
{'name': 'Elven chain', 'bonus': 0, 'cost': 5150, 'url':''},
{'name': 'Rhino hide', 'bonus': 0, 'cost': 5165, 'url':''},
{'name': 'Adamantine breastplate', 'bonus': 0, 'cost': 10200, 'url':''},
{'name': 'Dwarven plate', 'bonus': 0, 'cost': 16500, 'url':''},
{'name': 'Banded mail of luck', 'bonus': 0, 'cost': 18900, 'url':''},
{'name': 'Celestial armor', 'bonus': 0, 'cost': 22400, 'url':''},
{'name': 'Plate armor of the deep', 'bonus': 0, 'cost': 24650, 'url':''},
{'name': 'Breastplate of command', 'bonus': 0, 'cost': 25400, 'url':''},
{'name': 'Mithral full plate of speed', 'bonus': 0, 'cost': 26500, 'url':''},
{'name': 'Demon armor', 'bonus': 0, 'cost': 52260, 'url':''},
];
};
Armors.getSpecific = function(type) {
var roll = _.random(1,100);
var armor = {};
if(type == 'minor') {
switch(true) {
case (roll <= 50): armor = Armors.getSpecifics()[0]; break;
case (roll <= 80): armor = Armors.getSpecifics()[1]; break;
case (roll <= 100): armor = Armors.getSpecifics()[2]; break;
}
}
else if(type == 'medium') {
switch(true) {
case (roll <= 25): armor = Armors.getSpecifics()[0]; break;
case (roll <= 45): armor = Armors.getSpecifics()[1]; break;
case (roll <= 57): armor = Armors.getSpecifics()[2]; break;
case (roll <= 67): armor = Armors.getSpecifics()[3]; break;
case (roll <= 82): armor = Armors.getSpecifics()[4]; break;
case (roll <= 97): armor = Armors.getSpecifics()[5]; break;
case (roll <= 100): armor = Armors.getSpecifics()[6]; break;
}
}
else if(type == 'major') {
switch(true) {
case (roll <= 10): armor = Armors.getSpecifics()[4]; break;
case (roll <= 20): armor = Armors.getSpecifics()[5]; break;
case (roll <= 32): armor = Armors.getSpecifics()[6]; break;
case (roll <= 50): armor = Armors.getSpecifics()[7]; break;
case (roll <= 60): armor = Armors.getSpecifics()[8]; break;
case (roll <= 75): armor = Armors.getSpecifics()[9]; break;
case (roll <= 90): armor = Armors.getSpecifics()[10]; break;
case (roll <= 100): armor = Armors.getSpecifics()[11]; break;
}
}
return armor;
};
Armors.getArmors = function() {
//5 possible roll'able armors. Specific type of armor is left up to DM
return [
{'name': '+1 armor', 'bonus': 1, 'cost': 1000},
{'name': '+2 armor', 'bonus': 2, 'cost': 4000},
{'name': '+3 armor', 'bonus': 3, 'cost': 9000},
{'name': '+4 armor', 'bonus': 4, 'cost': 16000},
{'name': '+5 armor', 'bonus': 5, 'cost': 25000},
{'name': '+6 armor', 'bonus': 6, 'cost': 36000},
{'name': '+7 armor', 'bonus': 7, 'cost': 49000},
{'name': '+8 armor', 'bonus': 8, 'cost': 64000},
{'name': '+9 armor', 'bonus': 9, 'cost': 81000},
{'name': '+10 armor', 'bonus': 10,'cost': 10000}
];
};
Armors.getSpecials = function() {
return [
{'name': 'Glamered', 'bonus': 0, 'cost': 2700},
{'name': 'Light Fortification', 'bonus': 1, 'cost': 0},
{'name': 'Slick', 'bonus': 0, 'cost': 3750},
{'name': 'Shadow', 'bonus': 0, 'cost': 3750},
{'name': 'Spell resistance (13)', 'bonus': 2, 'cost': 0},
{'name': 'Improved Slick', 'bonus': 0, 'cost': 15000},
{'name': 'Improved Shadow', 'bonus': 0, 'cost': 15000},
{'name': 'Energy resistance (' + Grimoire.getEnergyResistance() + ')', 'bonus': 0, 'cost': 18000},
{'name': 'Ghost touch', 'bonus': 3, 'cost': 0},
{'name': 'Invulnerability', 'bonus': 3, 'cost': 0},
{'name': 'Moderate Fortification', 'bonus': 3, 'cost': 0},
{'name': 'Spell resistance (15)', 'bonus': 3, 'cost': 0},
{'name': 'Wild', 'bonus': 3, 'cost': 0},
{'name': 'Slick, greater', 'bonus': 0, 'cost': 33750},
{'name': 'Shadow, greater', 'bonus': 0, 'cost': 33750},
{'name': 'Improved Energy resistance (' + Grimoire.getEnergyResistance() + ')', 'bonus': 0, 'cost': 42000},
{'name': 'Spell resistance (17)', 'bonus': 4, 'cost': 0},
{'name': 'Etherealness', 'bonus': 0, 'cost': 49000},
{'name': 'Undead controlling', 'bonus': 0, 'cost': 49000},
{'name': 'Fortification, heavy', 'bonus': 5, 'cost': 0},
{'name': 'Spell resistance (19)', 'bonus': 5, 'cost': 0},
{'name': 'Energy resistance, greater (' + Grimoire.getEnergyResistance() + ')', 'bonus': 0, 'cost': 66000}
//100 Roll again twice
];
};
Armors.getSpecial = function(type) {
var roll = _.random(1,100);
var s1, s2;
if(type == 'minor') {
switch(true) {
case (roll <= 25): return Armors.getSpecials()[0];
case (roll <= 32): return Armors.getSpecials()[1];
case (roll <= 52): return Armors.getSpecials()[2];
case (roll <= 92): return Armors.getSpecials()[3];
case (roll <= 96): return Armors.getSpecials()[4];
case (roll <= 97): return Armors.getSpecials()[5];
case (roll <= 99): return Armors.getSpecials()[6];
case (roll <= 100): //roll twice
s1 = Armors.getSpecial('minor');
s2 = Armors.getSpecial('minor');
return {'name': s1.name + ' ' + s2.name, 'bonus': s1.bonus + s2.bonus};
}
}
else if(type == 'medium') {
switch(true) {
case (roll <= 5): return Armors.getSpecials()[0];
case (roll <= 8): return Armors.getSpecials()[1];
case (roll <= 11): return Armors.getSpecials()[2];
case (roll <= 17): return Armors.getSpecials()[3];
case (roll <= 19): return Armors.getSpecials()[4];
case (roll <= 29): return Armors.getSpecials()[5];
case (roll <= 49): return Armors.getSpecials()[6];
case (roll <= 74): return Armors.getSpecials()[7];
case (roll <= 79): return Armors.getSpecials()[8];
case (roll <= 84): return Armors.getSpecials()[9];
case (roll <= 89): return Armors.getSpecials()[10];
case (roll <= 94): return Armors.getSpecials()[11];
case (roll <= 99): return Armors.getSpecials()[12];
case (roll <= 100): //roll twice
s1 = Armors.getSpecial('medium');
s2 = Armors.getSpecial('medium');
return {'name': s1.name + ' ' + s2.name, 'bonus': s1.bonus + s2.bonus};
}
}
else if(type == 'major') {
switch(true) {
case (roll <= 3): return Armors.getSpecials()[0];
case (roll <= 4): return Armors.getSpecials()[1];
case (roll <= 7): return Armors.getSpecials()[5];
case (roll <= 13): return Armors.getSpecials()[6];
case (roll <= 28): return Armors.getSpecials()[7];
case (roll <= 33): return Armors.getSpecials()[8];
case (roll <= 35): return Armors.getSpecials()[9];
case (roll <= 40): return Armors.getSpecials()[10];
case (roll <= 42): return Armors.getSpecials()[11];
case (roll <= 43): return Armors.getSpecials()[12];
case (roll <= 48): return Armors.getSpecials()[13];
case (roll <= 58): return Armors.getSpecials()[14];
case (roll <= 83): return Armors.getSpecials()[15];
case (roll <= 88): return Armors.getSpecials()[16];
case (roll <= 89): return Armors.getSpecials()[17];
case (roll <= 90): return Armors.getSpecials()[18];
case (roll <= 92): return Armors.getSpecials()[19];
case (roll <= 94): return Armors.getSpecials()[20];
case (roll <= 99): return Armors.getSpecials()[21];
case (roll <= 100): //roll twice
s1 = Armors.getSpecial('major');
s2 = Armors.getSpecial('major');
return {'name': s1.name + ' ' + s2.name, 'bonus': s1.bonus + s2.bonus};
}
}
if(['minor','medium','major'].indexOf(type) >= 0 && roll == 100) {
var special1 = Armors.getSpecial(type);
var special2 = Armors.getSpecial(type);
//there exists a possibility of getting the same bonus
//this is hilarious and has not been fixed
if(special1.bonus + special2.bonus <= 10) {
return {'name': special1.name + ' ' + special2.name,
'bonus': special1.bonus + special2.bonus,
'cost': special1.cost + special2.cost
};
}
else {
//return the special with the better bonus.
return (special1.bonus > special2.bonus ? special1 : special2);
}
}
};
+313 -47
View File
@@ -324,9 +324,11 @@ var Grimoire = function(config) { // jshint ignore:line
if(itemType == TYPES.SCROLLS) {
item = self.getScroll(quality, options);
}
//POTIONS
else if(itemType == TYPES.POTIONS) {
item = self.getPotion(quality, options);
}
//WANDS
else if(itemType == TYPES.WANDS) {
item = self.getWand(quality, options);
}
@@ -334,6 +336,9 @@ var Grimoire = function(config) { // jshint ignore:line
else if(itemType == TYPES.WONDROUS_ITEMS) {
item = self.getWondrousItem(quality, options);
}
else if(itemType == TYPES.WEAPONS) {
item = self.getWeapon(quality, options);
}
//EVERYTHING ELSE
else {
//Select the item source based on the quality and item type
@@ -341,7 +346,6 @@ var Grimoire = function(config) { // jshint ignore:line
//EXCEPTIONS FOR ARMOR_AND_SHEILDS
//EXCEPTIONS FOR WEAPONS
//CHANCE FOR INTELLIGENT WEAPONS, RINGS, RODS, STAVES, OR WONDROUS ITEMS
item = self.getWeightedItem(source.data[itemType].data, quality);
@@ -355,6 +359,8 @@ var Grimoire = function(config) { // jshint ignore:line
return item;
};
//options.maxRoll - override the maximul value that can be rolled for these items
// default is the sum of the quality weights
this.getWeightedItem = function(itemData, quality, options) {
options = options ? options : {};
var chance = (self.chance ? self.chance : options.seed ? new Chance(options.seed) : new Chance());
@@ -374,7 +380,7 @@ var Grimoire = function(config) { // jshint ignore:line
}
}
console.error('Could not find valid '+quality+'item in',itemData);
}
};
this.getSpells = function(level, count, options) {
options = options ? options : {};
@@ -470,28 +476,13 @@ var Grimoire = function(config) { // jshint ignore:line
var chance = (self.chance ? self.chance : options.seed ? new Chance(options.seed) : new Chance());
var cost = [25, 50, 300, 750];
if(!level || level < 0 || level > 4) {
var roll = chance.d100();
if(quality == QUALITIES.MINOR) {
switch(true) {
case (roll <= 20): level = 0; break;
case (roll <= 60): level = 1; break;
case (roll <= 100): level = 2; break;
}
}
else if(quality == QUALITIES.MEDIUM) {
switch(true) {
case (roll <= 20): level = 1; break;
case (roll <= 60): level = 2; break;
case (roll <= 100): level = 3; break;
}
}
else if(quality == QUALITIES.MAJOR) {
switch(true) {
case (roll <= 20): level = 2; break;
case (roll <= 100): level = 3; break;
}
}
if(!level || level < 0 || level > 3) {
var weights = {};
weights[QUALITIES.MINOR] = [20, 40, 40, 0];
weights[QUALITIES.MEDIUM] = [ 0, 20, 40, 40];
weights[QUALITIES.MAJOR] = [ 0, 0, 20, 80];
level = chance.weighted([0,1,2,3], weights[quality]);
}
options.typeOverride = TYPES.POTIONS;
options.potionLevel = level;
@@ -514,26 +505,12 @@ var Grimoire = function(config) { // jshint ignore:line
if(!level || level < 0 || level > 4) {
var roll = chance.d100();
if(quality == QUALITIES.MINOR) {
switch(true) {
case (roll <= 5): level = 0; break;
case (roll <= 60): level = 1; break;
case (roll <= 100): level = 2; break;
}
}
else if(quality == QUALITIES.MEDIUM) {
switch(true) {
case (roll <= 60): level = 2; break;
case (roll <= 100): level = 3; break;
}
}
else if(quality == QUALITIES.MAJOR) {
switch(true) {
case (roll <= 60): level = 3; break;
case (roll <= 100): level = 4; break;
}
}
var weights = {};
weights[QUALITIES.MINOR] = [ 5, 55, 40, 0, 0];
weights[QUALITIES.MEDIUM] = [ 0, 0, 60, 40, 0];
weights[QUALITIES.MAJOR] = [ 0, 0, 0, 60, 40];
level = chance.weighted([0,1,2,3,4], weights[quality]);
}
options.wandLevel = level;
@@ -562,7 +539,8 @@ var Grimoire = function(config) { // jshint ignore:line
//make an intelligent item if we either want ALL intelligent items
//OR intelligent items are NOT disabled AND we roll under the chance threshold
if(options.allIntelligent || (!options.disableIntelligent && chance.d100() <= (options.intelligenceChance || 1))) {
item.intelligence = 'WOOHOO I AM INTELLIGENT!';
item.intelligence = self.getIntelligence(item.cost, options); //'WOOHOO I AM INTELLIGENT!';
item.cost += item.intelligence.cost;
}
return item;
};
@@ -592,6 +570,12 @@ var Grimoire = function(config) { // jshint ignore:line
bane = bane.replace(/GET_OUTSIDER_TYPE/, self.getOutsider(options));
return bane;
};
this.getEnergyType = function(options) {
options = options ? options : {};
var chance = (self.chance ? self.chance : options.seed ? new Chance(options.seed) : new Chance());
return chance.pick(_.values(ENERGY_TYPES));
};
//type is 'armor', 'shield', 'melee', or 'ranged'
//options.excludeSpecials can contain a list of specials you do NOT want to get
@@ -633,8 +617,10 @@ var Grimoire = function(config) { // jshint ignore:line
} while(options.excludeSpecials.indexOf(special) != -1); //if we have a duplicate, try again
//EXCEPTION for Bane special
if(special.name.indexOf('GET_BANE_TYPE')) {
if(/GET_BANE_TYPE/.test(special.name)) {
special.name = special.name.replace(/GET_BANE_TYPE/, self.getBane(options));
} else if(/GET_ENERGY_RESISTANCE_TYPE/.test(special.name)) {
special.name = special.name.replace(/GET_ENERGY_RESISTANCE_TYPE/, self.getEnergyType(options));
}
return [special]; //could contain one or more specials
@@ -767,11 +753,24 @@ var Grimoire = function(config) { // jshint ignore:line
//30% chance to be glowing
if(options.allIntelligent ||
(!options.disableIntelligent && chance.d100() <= (options.intelligenceChance || 1))) {
weapon.intelligence = 'WOOHOO I AM INTELLIGENT!';
var cost = weapon.baseCost + 2000 * Math.pow(weapon.bonus, 2);
weapon.intelligence = self.getIntelligence(cost, options); //'WOOHOO I AM INTELLIGENT!';
weapon.cost += weapon.intelligence.cost;
}
if(!options.disableGlowing && chance.d100() <= (options.glowingChance || 30)) {
weapon.glowing = true;
}
weapon.print = function() {
var ret = 'Name: ';
ret += this.glowing ? 'Glowing ' : '';
ret += this.bonus > 0 ? ('+' + this.bonus + ' ') : '';
ret += this.specials.length > 0 ? _.map(this.specials, function(s) { return s.name;}).join(', ') + ' ' : '';
ret += this.name ? this.name : (this.type + ' weapon');
ret += ';';
ret += this.intelligence.print ? 'Intelligence: [' + this.intelligence.print() + '];' : '';
ret += 'Cost: ' + (this.baseCost + 2000 * Math.pow(weapon.bonus, 2) + this.intelligence.cost) + 'gp';
return ret;
};
return weapon;
};
@@ -804,6 +803,273 @@ var Grimoire = function(config) { // jshint ignore:line
return alignment;
};
//options.cl can be Chaotic, Neutral, or Lawful
//options.ge can be Good, Neutral, or Evil
this.getDeity = function(options) {
options = options ? options : {};
var chance = (self.chance ? self.chance : options.seed ? new Chance(options.seed) : new Chance());
var cl = options.cl || chance.pick(['Chaotic', 'Neutral', 'Lawful']);
var ge = options.ge || chance.pick(['Good', 'Neutral', 'Evil']);
var deity = {};
deity.name = chance.pick(self.Deities.data[cl][ge]);
deity.alignment = (cl == 'Neutral' && ge == 'Neutral') ? 'True Neutral' : (cl + ' ' + ge);
return deity;
};
//baseCost is the base cost of the item the intelligence is being made for.
//This directly affects the intelligence's ego score!
//baseCost also directly affects the probability of the number of special abilities an intelligence will have
//options.numPowers
//options.purposeChance
//options.numDedicatedPowers
this.getIntelligence = function(baseCost, options) {
baseCost = baseCost || 0;
options = options || {};
var chance = (self.chance ? self.chance : options.seed ? new Chance(options.seed) : new Chance());
var i = {}; //intelligence object. we'll be referencing this a LOT
//***BASE VALUES***
i.cost = 500; //base starting cost
i.ego = 0;
//Base cost ego modifier
switch(true) {
case (baseCost <= 1000): i.ego += 0; break;
case (baseCost <= 5000): i.ego += 1; break;
case (baseCost <= 10000): i.ego += 2; break;
case (baseCost <= 20000): i.ego += 3; break;
case (baseCost <= 50000): i.ego += 4; break;
case (baseCost <= 100000): i.ego += 6; break;
case (baseCost <= 200000): i.ego += 8; break;
case (baseCost > 200000): i.ego += 12; break;
}
//***ITEM ABILITY STATS***
var statScores = [
{'score': 10, 'costMod': 0, 'egoMod': 0},
{'score': 11, 'costMod': 200, 'egoMod': 0},
{'score': 12, 'costMod': 500, 'egoMod': 1},
{'score': 13, 'costMod': 700, 'egoMod': 1},
{'score': 14, 'costMod': 1000, 'egoMod': 2},
{'score': 15, 'costMod': 1400, 'egoMod': 2},
{'score': 16, 'costMod': 2000, 'egoMod': 3},
{'score': 17, 'costMod': 2800, 'egoMod': 3},
{'score': 18, 'costMod': 4000, 'egoMod': 4},
{'score': 19, 'costMod': 5200, 'egoMod': 4},
{'score': 20, 'costMod': 8000, 'egoMod': 5},
];
var statWeights = [10, 10, 20, 10, 20, 5, 5, 5, 5, 5, 5];
i.stats = {};
['intelligence', 'wisdom', 'charisma'].forEach(function(stat) {
var score = chance.weighted(statScores, statWeights);
i.stats[stat] = score.score;
i.cost += score.costMod;
i.ego += score.egoMod;
});
i.alignment = self.getAlignment(options);
//***ITEM COMMUNICATION AND SENSES***
//get communication ability for the item.
var communicationTypes = [
{'description': 'Empathy', 'costMod': 0, 'egoMod': 0},
{'description': 'Speech', 'costMod': 500, 'egoMod': 0},
{'description': 'Telepathy', 'costMod': 1000, 'egoMod': 1},
];
var communicationWeights = [3,4,3]; //There was no roll table so I made this up
var communication = chance.weighted(communicationTypes, communicationWeights);
//get senses for the item. there was no roll table so I made this up
var basicSenses = [
{'description': 'Senses (30 ft.)', 'costMod': 0, 'egoMod': 0},
{'description': 'Senses (60 ft.)', 'costMod': 500, 'egoMod': 0},
{'description': 'Senses (120 ft.)', 'costMod': 1000, 'egoMod': 0},
];
var basicSensesWeights = [5,3,2]; //There was no roll table so I made this up
var basicSense = chance.weighted(basicSenses, basicSensesWeights);
//get special senses for the item.
var specialSenses = [
{'description': '', 'costMod': 0, 'egoMod': 0},
{'description': 'Darkvision', 'costMod': 500, 'egoMod': 0},
{'description': 'Blindsense', 'costMod': 5000, 'egoMod': 1},
{'description': 'Read languages', 'costMod': 1000, 'egoMod': 1},
{'description': 'Read magic', 'costMod': 2000, 'egoMod': 1},
];
//There was no roll table so I made this up and limited it to only 1 special per item
var specialSensesWeights = [50, 20, 5, 15, 10];
var specialSense = chance.weighted(specialSenses, specialSensesWeights);
i.communication = communication.description;
i.senses = basicSense.description + (specialSense.description ? ', ' + specialSense.description : '');
i.cost += communication.costMod + basicSense.costMod + specialSense.costMod;
i.ego += communication.egoMod + basicSense.egoMod + specialSense.egoMod;
//***ITEM POWERS***
//Get item powers!
var powerCountWeights = [1,1,1,1,1];
//The probability for more powers is directly related to the base cost of the item
//I made up these roll weights. references the same basecost as the basic ego modifier
switch(true) {
case (baseCost <= 1000): powerWeights = [6,4,0,0,0]; break;
case (baseCost <= 5000): powerWeights = [3,4,3,0,0]; break;
case (baseCost <= 10000): powerWeights = [2,3,4,1,0]; break;
case (baseCost <= 20000): powerWeights = [1,3,4,2,0]; break;
case (baseCost <= 50000): powerWeights = [0,2,4,3,1]; break;
case (baseCost <= 100000): powerWeights = [0,1,3,4,2]; break;
case (baseCost <= 200000): powerWeights = [0,0,2,5,3]; break;
case (baseCost > 200000): powerWeights = [0,0,0,6,4]; break;
}
var powerWeights = _.map(self.ItemPowers, function(p) { return p.weight; });
i.powers = [];
var reSkill = /GET_ITEM_SKILL/;
var reSpell = /GET_SPELL_LEVEL_(.)/; //for spell levels 0-9
//Another option would be to do this with _.sample but it does not support weights
_.times((options.numPowers || chance.weighted(_.range(1,6), powerCountWeights)), function() {
var power = {};
do {
power = _.clone(chance.weighted(_.clone(self.ItemPowers), powerWeights));
if(reSkill.test(power.description)) {
power.description = power.description.replace(reSkill, chance.pick(self.ItemSkills).name);
}
else if (reSpell.test(power.description)) {
var spellLevel = reSpell.exec(power.description)[1];
power.spell = self.getSpell(spellLevel, options); //add the spell onto the power for later reference
power.description = power.description.replace(reSpell, power.spell.name);
}
} while(_.findWhere(i.powers, {'description': power.description}) && !power.repeatable); //power exists in item powers and is not repeatable
if(_.findWhere(i.powers, {'description': power.description})) { //if we selected an existing but repeatable power
//add the new power values to the old power
var oldPower = _.findWhere(i.powers, {'description': power.description});
oldPower.costMod += power.costMod;
oldPower.egoMod += power.egoMod;
oldPower.value += power.value;
}
else {
i.powers.push(power);
}
});
//Set for the next section
var bonusLanguages = 0;
//Finalize powers
i.powers.forEach(function(p) {
p.description = p.description.replace(/#/, p.value);
i.ego += p.egoMod;
i.cost += p.costMod;
if(/Linguistics/.test(p.description)) { //check if we got any ranks in linguistics
bonusLanguages += p.value;
}
//clean up the power
delete p.value;
delete p.egoMod;
delete p.costMod;
delete p.weight;
delete p.repeatable;
//final power should only have description and spell
});
//***ITEM BONUS LANGUAGES***
i.languages = ['Common']; //ALL intelligent items know Common
//extra languages are based on intelligence and ranks in Linguistics
bonusLanguages += Math.floor((i.stats.intelligence-10)/2);
//pick is safe even if we have more bonusLanguages than exist
i.languages.concat(chance.pick(self.Languages.data, bonusLanguages));
//***ITEM PURPOSE***
//there was NO roll chart for determining if an item has a purpose so I made this up
//I figure 30% of the time sounds good
i.purpose = '';
i.dedicatedPowers = [];
if(chance.d100() <= (options.purposeChance || 30)) {
var reBane = /GET_BANE/;
var reHumOrOut = /GET_HUMANOID_OR_OUTSIDER_TYPE/;
var reDeity = /GET_DEITY/;
//get purpose
var purpose = chance.weighted(_.clone(self.ItemPurposes),
_.map(self.ItemPurposes, function(p) { return p.weight; }));
i.purpose = purpose.description;
i.ego += purpose.egoMod;
if(reBane.test(i.purpose)) {
i.purpose = i.purpose.replace(reBane, self.getBane(options));
}
else if(reHumOrOut.test(i.purpose)) {
i.purpose = i.purpose.replace(reHumOrOut,
chance.pick(['Humanoids (' + self.getHumanoid(options) + ')',
'Outsiders (' + self.getOutsider(options) + ')']));
}
else if(reDeity.test(i.purpose)) {
var deity = self.getDeity(options);
i.purpose = i.purpose.replace(reDeity, deity.name + ' (' + deity.alignment + ')');
}
//console.log(i.purpose.description);
i.dedicatedPowers = []; //chance.pick()
//I decided that purposed items get between 1-3 dedicated powers, heavily leaning on 1
var numDedicatedPowers = options.numDedicatedPowers || chance.weighted([1,2,3], [7,2,1]);
_.times(numDedicatedPowers, function() {
var power = {};
do {
power = _.clone(chance.weighted(self.ItemDedicatedPowers,
_.map(self.ItemDedicatedPowers, function(p) { return p.weight; })));
if (reSpell.test(power.description)) { //as in the normal powers
var spellLevel = reSpell.exec(power.description)[1];
power.spell = self.getSpell(spellLevel, options); //add the spell onto the power for later reference
power.description = power.description.replace(reSpell, power.spell.name);
}
//don't allow for duplicate dedicated powers
} while(_.findWhere(i.dedicatedPowers, {'description': power.description}));
//finalize dedicated power
i.cost += power.costMod;
i.ego += power.egoMod;
delete power.costMod;
delete power.egoMod;
delete power.weight;
i.dedicatedPowers.push(power);
});
}
//***PRINT FUNCTION***
i.print = function() {
var ret = '';
ret += 'Alignment: ' + this.alignment + ';';
ret += 'Stats: Ego ' + this.ego + ', Int ' + this.stats.intelligence + ', ' +
'Wis ' + this.stats.wisdom + ', ' +
'Cha ' + this.stats.charisma + ';';
ret += 'Communication: ' + this.communication + ' (' + this.languages.join(',' ) + ');';
ret += 'Senses: ' + this.senses + ';';
ret += 'Powers: ' + _.map(this.powers, function(p) { return p.description; }).join(', ') + ';';
if(this.purpose) {
ret += 'Purpose: ' + this.purpose + ';';
ret += 'Dedicated Powers: ' + _.map(this.dedicatedPowers, function(p) {return p.description; }).join(', ') + ';';
}
ret += 'Cost: ' + i.cost + 'gp';
return ret;
};
return i; //object intelligence
};
};
-390
View File
@@ -1,390 +0,0 @@
/*global _:false */
/*global Grimoire:true, Spells:true, Weapons:true */
'use strict';
Grimoire.alignments = ['Chaotic good', 'Chaotic neutral', 'Chaotic evil', 'Neutral evil',
'Lawful evil', 'Lawful good', 'Lawful neutral', 'Neutral good', 'True neutral']; //9 alignments
Grimoire.getAlignment = function() {
var roll = _.random(1,100);
switch(true) {
case (roll <= 10): return 'Chaotic good';
case (roll <= 20): return 'Chaotic neutral';
case (roll <= 35): return 'Chaotic evil';
case (roll <= 45): return 'Neutral evil';
case (roll <= 55): return 'Lawful evil';
case (roll <= 70): return 'Lawful good';
case (roll <= 80): return 'Lawful neutral';
case (roll <= 90): return 'Neutral good';
case (roll <= 100): return 'True neutral';
}
};
var Intelligence = {};
Intelligence.abilityScore = [
//ability_score = [score, base price modifier, ego modifier]
{'score': 10, 'priceMod': 0, 'egoMod': 0},
{'score': 11, 'priceMod': 200, 'egoMod': 0},
{'score': 12, 'priceMod': 500, 'egoMod': 1},
{'score': 13, 'priceMod': 700, 'egoMod': 1},
{'score': 14, 'priceMod': 1000, 'egoMod': 2},
{'score': 15, 'priceMod': 1400, 'egoMod': 2},
{'score': 16, 'priceMod': 2000, 'egoMod': 3},
{'score': 17, 'priceMod': 2800, 'egoMod': 3},
{'score': 18, 'priceMod': 4000, 'egoMod': 4},
{'score': 19, 'priceMod': 5200, 'egoMod': 4},
{'score': 20, 'priceMod': 8000, 'egoMod': 5},
];
Intelligence.getAbilityScore = function() {
var roll = _.random(1,100);
switch(true) {
case (roll <= 10): return Intelligence.abilityScore[0];
case (roll <= 20): return Intelligence.abilityScore[1];
case (roll <= 40): return Intelligence.abilityScore[2];
case (roll <= 50): return Intelligence.abilityScore[3];
case (roll <= 70): return Intelligence.abilityScore[4];
case (roll <= 75): return Intelligence.abilityScore[5];
case (roll <= 80): return Intelligence.abilityScore[6];
case (roll <= 85): return Intelligence.abilityScore[7];
case (roll <= 90): return Intelligence.abilityScore[8];
case (roll <= 95): return Intelligence.abilityScore[9];
case (roll <= 100): return Intelligence.abilityScore[10];
}
};
Intelligence.skills = {
//Craft has been left off the skills list since an object would have a hard time crafting anything
'int': ['Appraise', 'Knowledge (arcana)', 'Knowledge (dungeoneering)', 'Knowledge (engineering)',
'Knowledge (geography)', 'Knowledge (history)', 'Knowledge (local)', 'Knowledge (nature)',
'Knowledge (nobility)', 'Knowledge (planes)', 'Knowledge (religion)', 'Linguistics', 'Spellcraft'],
'cha': ['Bluff', 'Diplomacy', 'Intimidate', 'Perform'],
'wis': ['Perception', 'Sense Motive', 'Survival'],
};
Intelligence.getSkill = function (type) {
if(['int','cha','wis'].indexOf(type) >= 0) {
return _.sample(Intelligence.skills[type]);
}
else {
return _(Intelligence.skills.int)
.concat(Intelligence.skills.cha)
.concat(Intelligence.skills.wis)
.sample();
}
};
//I've tried to keep things orderly in public arrays but item powers are a bit messy
//item_power = [description, base price modifier, ego modifier]
Intelligence.getItemPower = function() {
var roll = _.random(1,100);
switch(true) {
case (roll <= 10):
return {'description': 'Item can cast ' + Spells.getLevelSpell(0).name + ' at will',
'priceMod': 1000, 'egoMod': 1};
case (roll <= 20):
return {'description': 'Item can cast ' + Spells.getLevelSpell(1).name + ' 3/day',
'priceMod': 1200, 'egoMod': 1};
case (roll <= 25):
return {'description': 'Item can use Magic Aura on itself at will',
'priceMod': 2000, 'egoMod': 1};
case (roll <= 35):
return {'description': 'Item can cast ' + Spells.getLevelSpell(2).name + ' 1/day',
'priceMod': 2400, 'egoMod': 1};
case (roll <= 45):
return {'description': 'Item has 5 ranks in ' + Intelligence.getSkill(),
'priceMod': 2500, 'egoMod': 1};
case (roll <= 50):
return {'description': 'Item can sprout limbs and move with a speed of 10 feet',
'priceMod': 5000, 'egoMod': 1};
case (roll <= 55):
return {'description': 'Item can cast ' + Spells.getLevelSpell(3).name + ' 1/day',
'priceMod': 6000, 'egoMod': 1};
case (roll <= 60):
return {'description': 'Item can cast ' + Spells.getLevelSpell(2).name + ' 3/day',
'priceMod': 1000, 'egoMod': 1};
case (roll <= 70):
return {'description': 'Item has 10 ranks in ' + Intelligence.getSkill(),
'priceMod': 10000, 'egoMod': 2};
case (roll <= 75):
return {'description': 'Item can change shape into one other form of the same size',
'priceMod': 10000, 'egoMod': 2};
case (roll <= 80):
return {'description': 'Item can fly, as per the spell, at a speed of 30 feet',
'priceMod': 10000, 'egoMod': 2};
case (roll <= 85):
return {'description': 'Item can cast ' + Spells.getLevelSpell(4).name + ' 1/day',
'priceMod': 11200, 'egoMod': 2};
case (roll <= 90):
return {'description': 'Item can cast teleport itself 1/day',
'priceMod': 15000, 'egoMod': 2};
case (roll <= 95):
return {'description': 'Item can cast ' + Spells.getLevelSpell(3).name + ' 3/day',
'priceMod': 18000, 'egoMod': 2};
case (roll <= 100):
return {'description': 'Item can cast ' + Spells.getLevelSpell(4).name + ' 3/day',
'priceMod': 33600, 'egoMod': 2};
}
};
//this one was also a bit messy
//item_purpose = [description, ego modifier]
Intelligence.getItemPurpose = function() {
var roll = _.random(1,100);
switch(true) {
case (roll <= 20):
return {'description': 'Defeat/slay diametrically opposed alignment',
'egoMod': 2};
case (roll <= 30):
return {'description': 'Defeat/slay arcane spellcasters (including spellcasting monsters and those that use spell-like abilities)',
'egoMod': 2};
case (roll <= 40):
return {'description': 'Defeat/slay divine spellcasters (including divine entities and servitors)',
'egoMod': 2};
case (roll <= 50):
return {'description': 'Defeat/slay non-spellcasters',
'egoMod': 2};
case (roll <= 55):
return {'description': 'Defeat/slay all ' + Weapons.getBane().slice(8), //this probably isn't quite right but we'll keep it for now',
'egoMod': 2};
case (roll <= 60):
return {'description': 'Defeat/slay all ' + _.sample(['Humanoids (' + Grimoire.getHumanoidType() + ')', 'Outsiders (' + Grimoire.getOutsiderType() + ')']),
'egoMod': 2};
case (roll <= 70):
return {'description': 'Defend all ' + _.sample(['Humanoids (' + Grimoire.getHumanoidType() + ')', 'Outsiders (' + Grimoire.getOutsiderType() + ')']),
'egoMod': 2};
case (roll <= 80):
return {'description': 'Defeat/slay the servants of ' + Grimoire.getDeity(),
'egoMod': 2};
case (roll <= 90):
return {'description': 'Defend the servants of ' + Grimoire.getDeity(),
'egoMod': 2};
case (roll <= 95):
return {'description': 'Defeat/slay all (other than the item and the wielder)',
'egoMod': 2};
case (roll <= 100):
return {'description': 'Make something up! (GM discression)',
'egoMod': 2};
}
};
//another messy one
//dedicated_power = [description, base price modifier, ego modifier]
Intelligence.getDedicatedPower = function() {
var roll = _.random(1,100);
switch(true) {
case (roll <= 20):
return {'description': 'Item can detect any special purpose foes within 60 feet',
'priceMod': 10000, 'egoMod': 1};
case (roll <= 35):
return {'description': 'Item can cast ' + Spells.getLevelSpell(4).name + ' at will',
'priceMod': 56000, 'egoMod': 2};
case (roll <= 50):
return {'description': 'Wielder gets +2 luck bonus on attacks, saves, and checks',
'priceMod': 80000, 'egoMod': 2};
case (roll <= 65):
return {'description': 'Item can cast ' + Spells.getLevelSpell(5).name + ' at will',
'priceMod': 90000, 'egoMod': 2};
case (roll <= 80):
return {'description': 'Item can cast ' + Spells.getLevelSpell(6).name + ' at will',
'priceMod': 132000, 'egoMod': 2};
case (roll <= 95):
return {'description': 'Item can cast ' + Spells.getLevelSpell(7).name + ' at will',
'priceMod': 182000, 'egoMod': 2};
case (roll <= 100):
return {'description': 'Item can cast true resurrection on weilder, once per month',
'priceMod': 200000, 'egoMod': 2};
}
};
Intelligence.communication = [
{'description': 'Empathy', 'priceMod': 0, 'egoMod': 0},
{'description': 'Speech', 'priceMod': 500, 'egoMod': 0},
{'description': 'Telepathy', 'priceMod': 1000, 'egoMod': 1},
];
Intelligence.basicSenses = [
{'description': 'Senses (30 ft.)', 'priceMod': 0, 'egoMod': 0},
{'description': 'Senses (60 ft.)', 'priceMod': 500, 'egoMod': 0},
{'description': 'Senses (120 ft.)', 'priceMod': 1000, 'egoMod': 0},
];
Intelligence.specialSenses = [
{'description': '', 'priceMod': 0, 'egoMod': 0},
{'description': 'Darkvision', 'priceMod': 500, 'egoMod': 0},
{'description': 'Blindsense', 'priceMod': 5000, 'egoMod': 1},
{'description': 'Read languages', 'priceMod': 1000, 'egoMod': 1},
{'description': 'Read magic', 'priceMod': 2000, 'egoMod': 1},
];
//Common was left out since ALL intelligent items speak common
//Druidic was left out since only Druids know it
//I was thinking of separating languages into generally 'good' or 'evil' but realized that was more up to DM discression
Intelligence.languages = ['Abyssal', 'Aklo', 'Aquan', 'Auran', 'Celestial', 'Draconic',
'Dwarven', 'Elven', 'Giant', 'Gnome', 'Goblin', 'Gnoll', 'Halfling',
'Ignan', 'Infernal', 'Orc', 'Sylvan', 'Terran', 'Undercommon'];
//returns ['all stats, powers, and abilities', cost]
Intelligence.getItemIntelligence = function(basePrice) {
var cost = 500 + (basePrice === undefined ? 0 : basePrice);
var ego = 0;
switch(true) {
case (basePrice <= 1000): ego += 0; break;
case (basePrice <= 5000): ego += 1; break;
case (basePrice <= 10000): ego += 2; break;
case (basePrice <= 20000): ego += 3; break;
case (basePrice <= 50000): ego += 4; break;
case (basePrice <= 100000): ego += 6; break;
case (basePrice <= 200000): ego += 8; break;
case (basePrice > 200000): ego += 12; break;
}
var sInt = Intelligence.getAbilityScore();
var sCha = Intelligence.getAbilityScore();
var sWis = Intelligence.getAbilityScore();
cost += sInt.priceMod + sCha.priceMod + sWis.priceMod;
ego += sInt.egoMod + sCha.egoMod + sWis.egoMod;
var languages = ['Common'];
var bonusLanguages = Math.floor((sInt.score-10)/2);
//extra languages will be calculated after we see if it picked up ranks in Linguistics
var communication = {};
var roll = _.random(1,100);
//get communication ability for the item. there was no roll table so I made this up
switch(true) {
case (roll <= 30): communication = Intelligence.communication[0]; break;
case (roll <= 70): communication = Intelligence.communication[1]; break;
case (roll <= 100): communication = Intelligence.communication[2]; break;
}
var basicSenses = {};
//get senses for the item. there was no roll table so I made this up
roll = _.random(1,100);
switch(true) {
case (roll <= 50): basicSenses = Intelligence.basicSenses[0]; break;
case (roll <= 80): basicSenses = Intelligence.basicSenses[1]; break;
case (roll <= 100): basicSenses = Intelligence.basicSenses[2]; break;
}
var specialSenses = {};
//get special senses for the item. there was no roll table so I made this up
//and limited it to only 1 special per item
roll = _.random(1,100);
switch(true) {
case (roll <= 50): specialSenses = Intelligence.specialSenses[0]; break;
case (roll <= 70): specialSenses = Intelligence.specialSenses[0]; break;
case (roll <= 75): specialSenses = Intelligence.specialSenses[0]; break;
case (roll <= 90): specialSenses = Intelligence.specialSenses[0]; break;
case (roll <= 100): specialSenses = Intelligence.specialSenses[0]; break;
}
cost += communication.priceMod + basicSenses.priceMod + specialSenses.priceMod;
ego += communication.egoMod + basicSenses.egoMod + specialSenses.egoMod;
//Get item powers!
//So I was thinking of making the number of powers an item had somewhat based on the base cost
//but decided to instead roll it pure random items randomly get between 1-5 powers
//There is the possibility to get repeats of the SAME power
//In that case, I guess you would just add the numerical parts
// eg if 'fly at 30 ft/round' is rolled twice, it becomes 'fly at 60 ft/round'
var powers = [];
_.times(_.random(1,5), function() {
var power = Intelligence.getItemPower();
powers.push(power);
cost += power.priceMod;
ego += power.egoMod;
if(power.description.indexOf('linguistics') >= 0) {
bonusLanguages += parseInt(power.description.match(/\d+/)[0]);
}
});
//add any extra languages to the known languages list
languages = _(languages).concat(_.sample(Intelligence.languages, bonusLanguages)).value();
//determining purpose
//there was NO roll chart for determining if an item has a purpose so I made this up
//I figure 20% of the time sounds good
var purpose = {'description':'', 'egoMod': 0};
var dedicatedPowers = [];
if(_.random(1,100) > 80) {
purpose = Intelligence.getItemPurpose();
ego += purpose.egoMod;
var pPowersNum = 1;
//I decided that purposed items get between 1-3 dedicated powers, heavily leaning on 1
roll = _.random(1,100);
switch(true) {
case (roll <= 70): pPowersNum = 1; break;
case (roll <= 90): pPowersNum = 2; break;
case (roll <= 100): pPowersNum = 3; break;
}
_.times(pPowersNum, function() {
var pPower = Intelligence.getDedicatedPower();
dedicatedPowers.push(pPower);
cost += pPower.priceMod;
ego += pPower.egoMod;
});
}
var item = {};
item.alignment = Grimoire.getAlignment();
item.ego = ego;
item.intScore = sInt.score;
item.chaScore = sCha.score;
item.wisScore = sWis.score;
item.communication = communication;
item.languages = languages;
item.basicSenses = basicSenses;
item.specialSenses = specialSenses;
item.powers = powers;
item.purpose = purpose;
item.dedicatedPowers = dedicatedPowers;
item.cost = cost;
item.print = function() {
var retStr = 'Alignment: ' + this.alignment +
';Stats: Ego ' + this.ego + ' Int ' + this.intScore + ' Cha ' + this.chaScore + ' Wis ' + this.wisScore +
';Communication: ' + this.communication.description;
this.languages.forEach(function(l, index) { retStr += ((index === 0) ? ';Languages: ' : ', ') + l;});
retStr += ';Senses: ' + basicSenses.description + (!specialSenses.description) ? '' : (', ' + specialSenses.description);
this.powers.forEach(function(p, index) {
retStr += ((index === 0) ? ';Powers: ' : ', ') + p.description;
});
if(this.purpose.description) {
retStr += ';Purpose: ' + this.purpose.description;
this.dedicatedPowers.forEach(function(p, index) {
retStr += ((index === 0) ? ';Dedicated Powers: ' : ', ') + p.description;
});
}
retStr += ';Cost: ' + this.cost;
return retStr;
};
return item;
};
/*
purpose += ' Dedicated Powers: '
first = true
purpose_powers_num.times{
purpose_power, cost_bonus, ego_bonus = get_dedicated_power()
if first
purpose += purpose_power
first = false
else
purpose += ', ' + purpose_power
end
cost += cost_bonus
ego += ego_bonus
}
end
return ['Alignment: ' + alignment + ' Stats: Ego ' + ego.to_s + ' Int ' + stat_int.to_s + ' Cha ' + stat_cha.to_s + ' Wis ' +
stat_wis.to_s + senses_and_communication + item_languages + powers + purpose, cost]
end
end
*/
-166
View File
@@ -1,166 +0,0 @@
/*global _:false */
/*global Grimoire:true */
'use strict';
//TODO: Program the "Roll twice" logic
var Shields = {};
Shields.specificBaseUrl = 'http://paizo.com/pathfinderRPG/prd/magicItems/armor.html';
Shields.getSpecifics = function() {
return [
{'name': 'Darkwood buckler', 'bonus': 0, 'cost': 203, 'url': '#darkwood-buckler'},
{'name': 'Darkwood shield', 'bonus': 0, 'cost': 257, 'url': ''},
{'name': 'Mithral heavy shield', 'bonus': 0, 'cost': 1020, 'url': ''},
{'name': 'Caster\'s shield', 'bonus': 0, 'cost': 3153, 'url': ''},
{'name': 'Spined shield', 'bonus': 0, 'cost': 5580, 'url': ''},
{'name': 'Lion\'s shield', 'bonus': 0, 'cost': 9170, 'url': ''},
{'name': 'Winged shield', 'bonus': 0, 'cost': 17257, 'url': ''},
{'name': 'Absorbing shield', 'bonus': 0, 'cost': 5017, 'url': ''}
];
};
Shields.getSpecific = function(type) {
var roll = _.random(1,100);
var shield = {};
if(type == 'minor') {
switch(true) {
case (roll <= 30): shield = Shields.getSpecifics()[0]; break;
case (roll <= 80): shield = Shields.getSpecifics()[1]; break;
case (roll <= 95): shield = Shields.getSpecifics()[2]; break;
case (roll <= 100): shield = Shields.getSpecifics()[3]; break;
}
}
else if(type == 'medium') {
switch(true) {
case (roll <= 20): shield = Shields.getSpecifics()[0]; break;
case (roll <= 45): shield = Shields.getSpecifics()[1]; break;
case (roll <= 70): shield = Shields.getSpecifics()[2]; break;
case (roll <= 85): shield = Shields.getSpecifics()[3]; break;
case (roll <= 90): shield = Shields.getSpecifics()[4]; break;
case (roll <= 95): shield = Shields.getSpecifics()[5]; break;
case (roll <= 100): shield = Shields.getSpecifics()[6]; break;
}
}
else if(type == 'major') {
switch(true) {
case (roll <= 20): shield = Shields.getSpecifics()[3]; break;
case (roll <= 40): shield = Shields.getSpecifics()[4]; break;
case (roll <= 62): shield = Shields.getSpecifics()[5]; break;
case (roll <= 90): shield = Shields.getSpecifics()[6]; break;
case (roll <= 100): shield = Shields.getSpecifics()[7]; break;
}
}
return shield;
};
Shields.getShields = function() {
//5 possible roll'able shields. Specific type of shield is left up to DM
return [
{'name': '+1 shield', 'bonus': 1, 'cost': 1000},
{'name': '+2 shield', 'bonus': 2, 'cost': 4000},
{'name': '+3 shield', 'bonus': 3, 'cost': 9000},
{'name': '+4 shield', 'bonus': 4, 'cost': 16000},
{'name': '+5 shield', 'bonus': 5, 'cost': 25000},
{'name': '+6 shield', 'bonus': 6, 'cost': 36000},
{'name': '+7 shield', 'bonus': 7, 'cost': 49000},
{'name': '+8 shield', 'bonus': 8, 'cost': 64000},
{'name': '+9 shield', 'bonus': 9, 'cost': 81000},
{'name': '+10 shield', 'bonus': 10,'cost': 10000}
];
};
Shields.getSpecials = function() {
return [
{'name': 'Arrow catching', 'bonus': 1, 'cost': 0},
{'name': 'Bashing', 'bonus': 1, 'cost': 0},
{'name': 'Blinding', 'bonus': 1, 'cost': 0},
{'name': 'Light Fortification', 'bonus': 1, 'cost': 0},
{'name': 'Arrow deflection', 'bonus': 2, 'cost': 0},
{'name': 'Animated', 'bonus': 2, 'cost': 0},
{'name': 'Spell resistance (13)', 'bonus': 2, 'cost': 0},
{'name': 'Energy resistance (' + Grimoire.getEnergyResistance() + ')', 'bonus': 0, 'cost': 18000},
{'name': 'Ghost touch', 'bonus': 3, 'cost': 0},
{'name': 'Moderate Fortification', 'bonus': 3, 'cost': 0},
{'name': 'Spell resistance (15)', 'bonus': 3, 'cost': 0},
{'name': 'Wild', 'bonus': 3, 'cost': 0},
{'name': 'Improved Energy resistance (' + Grimoire.getEnergyResistance() + ')', 'bonus': 0, 'cost': 42000},
{'name': 'Spell resistance (17)', 'bonus': 4, 'cost': 0},
{'name': 'Undead controlling', 'bonus': 0, 'cost': 49000},
{'name': 'Fortification, heavy', 'bonus': 5, 'cost': 0},
{'name': 'Reflecting', 'bonus': 5, 'cost': 0},
{'name': 'Spell resistance (19)', 'bonus': 5, 'cost': 0},
{'name': 'Energy resistance, greater (' + Grimoire.getEnergyResistance() + ')', 'bonus': 0, 'cost': 6600}
];
};
Shields.getSpecial = function(type) {
var roll = _.random(1,100);
if(type == 'minor') {
switch(true) {
case (roll <= 20): return Shields.getSpecials()[0];
case (roll <= 40): return Shields.getSpecials()[1];
case (roll <= 50): return Shields.getSpecials()[2];
case (roll <= 75): return Shields.getSpecials()[3];
case (roll <= 92): return Shields.getSpecials()[4];
case (roll <= 97): return Shields.getSpecials()[5];
case (roll <= 99): return Shields.getSpecials()[6];
case (roll <= 100): /*roll twice*/ break;
}
}
else if(type == 'medium') {
switch(true) {
case (roll <= 10): return Shields.getSpecials()[0];
case (roll <= 20): return Shields.getSpecials()[1];
case (roll <= 25): return Shields.getSpecials()[2];
case (roll <= 40): return Shields.getSpecials()[3];
case (roll <= 50): return Shields.getSpecials()[4];
case (roll <= 57): return Shields.getSpecials()[5];
case (roll <= 59): return Shields.getSpecials()[6];
case (roll <= 79): return Shields.getSpecials()[7];
case (roll <= 85): return Shields.getSpecials()[8];
case (roll <= 95): return Shields.getSpecials()[9];
case (roll <= 98): return Shields.getSpecials()[10];
case (roll <= 99): return Shields.getSpecials()[11];
case (roll <= 100): /*roll twice*/ break;
}
}
else if(type == 'major') {
switch(true) {
case (roll <= 5): return Shields.getSpecials()[0];
case (roll <= 8): return Shields.getSpecials()[1];
case (roll <= 10): return Shields.getSpecials()[2];
case (roll <= 15): return Shields.getSpecials()[3];
case (roll <= 20): return Shields.getSpecials()[4];
case (roll <= 25): return Shields.getSpecials()[5];
case (roll <= 41): return Shields.getSpecials()[7];
case (roll <= 46): return Shields.getSpecials()[8];
case (roll <= 56): return Shields.getSpecials()[9];
case (roll <= 58): return Shields.getSpecials()[10];
case (roll <= 59): return Shields.getSpecials()[11];
case (roll <= 84): return Shields.getSpecials()[12];
case (roll <= 86): return Shields.getSpecials()[13];
case (roll <= 87): return Shields.getSpecials()[14];
case (roll <= 91): return Shields.getSpecials()[15];
case (roll <= 93): return Shields.getSpecials()[16];
case (roll <= 94): return Shields.getSpecials()[17];
case (roll <= 99): return Shields.getSpecials()[18];
case (roll <= 100): /*roll twice*/ break;
}
}
if(['minor','medium','major'].indexOf(type) >= 0 && roll == 100) {
var special1 = Shields.getSpecial(type);
var special2 = Shields.getSpecial(type);
//there exists a possibility of getting the same bonus or a bonus over +10
//this is hilarious and has not been fixed
if(special1.bonus + special2.bonus <= 10) {
return {'name': special1.name + ' ' + special2.name,
'bonus': special1.bonus + special2.bonus,
'cost': special1.cost + special2.cost
};
}
else {
//return the special with the better bonus.
return (special1.bonus > special2.bonus ? special1 : special2);
}
}
};
+15
View File
@@ -0,0 +1,15 @@
[
{ "name": "Aberations", "weight": 5},
{ "name": "Animals", "weight": 4},
{ "name": "Constructs", "weight": 7},
{ "name": "Dragons", "weight": 6},
{ "name": "Fey", "weight": 5},
{ "name": "Humanoids (GET_HUMANOID_TYPE)", "weight": 30},
{ "name": "Magical Beasts", "weight": 8},
{ "name": "Monstrous Humanoids", "weight": 5},
{ "name": "Oozes", "weight": 22},
{ "name": "Outsiders (GET_OUTSIDER_TYPE)", "weight": 16},
{ "name": "Plants", "weight": 2},
{ "name": "Undead", "weight": 8},
{ "name": "Vermin", "weight": 2}
]
+71
View File
@@ -0,0 +1,71 @@
{
"uniqueArmors": [
{"name": "Mithral shirt", "cost": 1100, "url": "#mithril-shirt", "weight": { "minor": 50, "medium": 25, "major": 0} },
{"name": "Dragonhide plate", "cost": 3300, "url":"", "weight": { "minor": 30, "medium": 20, "major": 0} },
{"name": "Elven chain", "cost": 5150, "url":"", "weight": { "minor": 20, "medium": 12, "major": 0} },
{"name": "Rhino hide", "cost": 5165, "url":"", "weight": { "minor": 0, "medium": 10, "major": 0} },
{"name": "Adamantine breastplate", "cost": 10200, "url":"", "weight": { "minor": 0, "medium": 15, "major": 10} },
{"name": "Dwarven plate", "cost": 16500, "url":"", "weight": { "minor": 0, "medium": 15, "major": 10} },
{"name": "Banded mail of luck", "cost": 18900, "url":"", "weight": { "minor": 0, "medium": 3, "major": 12} },
{"name": "Celestial armor", "cost": 22400, "url":"", "weight": { "minor": 0, "medium": 0, "major": 18} },
{"name": "Plate armor of the deep", "cost": 24650, "url":"", "weight": { "minor": 0, "medium": 0, "major": 10} },
{"name": "Breastplate of command", "cost": 25400, "url":"", "weight": { "minor": 0, "medium": 0, "major": 15} },
{"name": "Mithral full plate of speed", "cost": 26500, "url":"", "weight": { "minor": 0, "medium": 0, "major": 15} },
{"name": "Demon armor", "cost": 52260, "url":"", "weight": { "minor": 0, "medium": 0, "major": 10} }
],
"armorSpecials": [
{"name": "Glamered", "bonus": 0, "cost": 2700, "weight": {"minor": 25, "medium": 5, "major": 3} },
{"name": "Light Fortification", "bonus": 1, "cost": 0, "weight": {"minor": 7, "medium": 3, "major": 1} },
{"name": "Slick", "bonus": 0, "cost": 3750, "weight": {"minor": 20, "medium": 3, "major": 0} },
{"name": "Shadow", "bonus": 0, "cost": 3750, "weight": {"minor": 40, "medium": 6, "major": 0} },
{"name": "Spell resistance (13)", "bonus": 2, "cost": 0, "weight": {"minor": 4, "medium": 2, "major": 0} },
{"name": "Improved Slick", "bonus": 0, "cost": 15000, "weight": {"minor": 1, "medium": 10, "major": 3} },
{"name": "Improved Shadow", "bonus": 0, "cost": 15000, "weight": {"minor": 2, "medium": 20, "major": 6} },
{"name": "Energy resistance (GET_ENERGY_RESISTANCE_TYPE)", "bonus": 0, "cost": 18000, "weight": {"minor": 0, "medium": 25, "major": 15} },
{"name": "Ghost touch", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 5, "major": 5} },
{"name": "Invulnerability", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 5, "major": 2} },
{"name": "Moderate Fortification", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 5, "major": 5} },
{"name": "Spell resistance (15)", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 5, "major": 2} },
{"name": "Wild", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 5, "major": 1} },
{"name": "Slick, greater", "bonus": 0, "cost": 33750, "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Shadow, greater", "bonus": 0, "cost": 33750, "weight": {"minor": 0, "medium": 0, "major": 10} },
{"name": "Improved Energy resistance (GET_ENERGY_RESISTANCE_TYPE)", "bonus": 0, "cost": 42000, "weight": {"minor": 0, "medium": 0, "major": 30} },
{"name": "Spell resistance (17)", "bonus": 4, "cost": 0, "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Etherealness", "bonus": 0, "cost": 49000, "weight": {"minor": 0, "medium": 0, "major": 1} },
{"name": "Undead controlling", "bonus": 0, "cost": 49000, "weight": {"minor": 0, "medium": 0, "major": 1} },
{"name": "Fortification, heavy", "bonus": 5, "cost": 0, "weight": {"minor": 0, "medium": 0, "major": 2} },
{"name": "Spell resistance (19)", "bonus": 5, "cost": 0, "weight": {"minor": 0, "medium": 0, "major": 2} },
{"name": "Energy resistance, greater (GET_ENERGY_RESISTANCE_TYPE)", "bonus": 0, "cost": 66000, "weight": {"minor": 0, "medium": 0, "major": 5} }
],
"uniqueShields": [
{"name": "Darkwood buckler", "cost": 203, "url": "#darkwood-buckler", "weight": { "minor": 30, "medium": 20, "major": 0} },
{"name": "Darkwood shield", "cost": 257, "url": "", "weight": { "minor": 50, "medium": 25, "major": 0} },
{"name": "Mithral heavy shield", "cost": 1020, "url": "", "weight": { "minor": 15, "medium": 25, "major": 0} },
{"name": "Caster's shield", "cost": 3153, "url": "", "weight": { "minor": 5, "medium": 15, "major": 20} },
{"name": "Spined shield", "cost": 5580, "url": "", "weight": { "minor": 0, "medium": 5, "major": 20} },
{"name": "Lion's shield", "cost": 9170, "url": "", "weight": { "minor": 0, "medium": 5, "major": 22} },
{"name": "Winged shield", "cost": 17257, "url": "", "weight": { "minor": 0, "medium": 5, "major": 28} },
{"name": "Absorbing shield", "cost": 5017, "url": "", "weight": { "minor": 0, "medium": 0, "major": 10} }
],
"shieldSpecials": [
{"name": "Arrow catching", "bonus": 1, "cost": 0, "weight": {"minor": 20, "medium": 10, "major": 5} },
{"name": "Bashing", "bonus": 1, "cost": 0, "weight": {"minor": 20, "medium": 10, "major": 3} },
{"name": "Blinding", "bonus": 1, "cost": 0, "weight": {"minor": 10, "medium": 5, "major": 2} },
{"name": "Light Fortification", "bonus": 1, "cost": 0, "weight": {"minor": 25, "medium": 15, "major": 5} },
{"name": "Arrow deflection", "bonus": 2, "cost": 0, "weight": {"minor": 17, "medium": 10, "major": 5} },
{"name": "Animated", "bonus": 2, "cost": 0, "weight": {"minor": 5, "medium": 7, "major": 5} },
{"name": "Spell resistance (13)", "bonus": 2, "cost": 0, "weight": {"minor": 2, "medium": 2, "major": 0} },
{"name": "Energy resistance (GET_ENERGY_RESISTANCE_TYPE)", "bonus": 0, "cost": 18000, "weight": {"minor": 0, "medium": 20, "major": 16} },
{"name": "Ghost touch", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 6, "major": 5} },
{"name": "Moderate Fortification", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 10, "major": 10} },
{"name": "Spell resistance (15)", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 3, "major": 2} },
{"name": "Wild", "bonus": 3, "cost": 0, "weight": {"minor": 0, "medium": 1, "major": 1} },
{"name": "Improved Energy resistance (GET_ENERGY_RESISTANCE_TYPE)", "bonus": 0, "cost": 42000, "weight": {"minor": 0, "medium": 0, "major": 25} },
{"name": "Spell resistance (17)", "bonus": 4, "cost": 0, "weight": {"minor": 0, "medium": 0, "major": 2} },
{"name": "Undead controlling", "bonus": 0, "cost": 49000, "weight": {"minor": 0, "medium": 0, "major": 1} },
{"name": "Fortification, heavy", "bonus": 5, "cost": 0, "weight": {"minor": 0, "medium": 0, "major": 4} },
{"name": "Reflecting", "bonus": 5, "cost": 0, "weight": {"minor": 0, "medium": 0, "major": 2} },
{"name": "Spell resistance (19)", "bonus": 5, "cost": 0, "weight": {"minor": 0, "medium": 0, "major": 1} },
{"name": "Energy resistance, greater (GET_ENERGY_RESISTANCE_TYPE)", "bonus": 0, "cost": 6600, "weight": {"minor": 0, "medium": 0, "major": 5} }
]
}
+87
View File
@@ -0,0 +1,87 @@
{
"uniqueWeapons": [
{"name": "Sleep arrow", "cost": 132, "url": "#sleep-arrow", "weight": {"minor": 15, "medium": 0, "major": 0} },
{"name": "Screaming bolt", "cost": 267, "url":"", "weight": {"minor": 10, "medium": 0, "major": 0} },
{"name": "Silver dagger (masterwork)", "cost": 322, "url":"", "weight": {"minor": 20, "medium": 0, "major": 0} },
{"name": "Cold iron longsword (masterwork)", "cost": 330, "url":"", "weight": {"minor": 20, "medium": 0, "major": 0} },
{"name": "Javelin of lightning", "cost": 1500, "url":"", "weight": {"minor": 20, "medium": 9, "major": 0} },
{"name": "Slaying arrow", "cost": 2282, "url":"", "weight": {"minor": 10, "medium": 6, "major": 0} },
{"name": "Adamantine dagger", "cost": 3002, "url":"", "weight": {"minor": 5, "medium": 9, "major": 0} },
{"name": "Adamantine battleaxe", "cost": 3010, "url":"", "weight": {"minor": 10, "medium": 9, "major": 0} },
{"name": "Slaying arrow (greater)", "cost": 4057, "url":"", "weight": {"minor": 10, "medium": 4, "major": 0} },
{"name": "Shatterspike", "cost": 4315, "url":"", "weight": {"minor": 0, "medium": 3, "major": 0} },
{"name": "Dagger of venom", "cost": 8302, "url":"", "weight": {"minor": 0, "medium": 6, "major": 0} },
{"name": "Trident of warning", "cost": 10115, "url":"", "weight": {"minor": 0, "medium": 5, "major": 0} },
{"name": "Assassin\"s dagger", "cost": 10302, "url":"", "weight": {"minor": 0, "medium": 6, "major": 4} },
{"name": "Shifter\"s sorrow", "cost": 12780, "url":"", "weight": {"minor": 0, "medium": 5, "major": 3} },
{"name": "Trident of fish command", "cost": 18650, "url":"", "weight": {"minor": 0, "medium": 4, "major": 2} },
{"name": "Flame tongue", "cost": 20715, "url":"", "weight": {"minor": 0, "medium": 8, "major": 4} },
{"name": "Luck blade (0 wishes)", "cost": 22060, "url":"", "weight": {"minor": 0, "medium": 5, "major": 4} },
{"name": "Sword of subtlety", "cost": 22310, "url":"", "weight": {"minor": 0, "medium": 7, "major": 7} },
{"name": "Sword of the planes", "cost": 22315, "url":"", "weight": {"minor": 0, "medium": 5, "major": 7} },
{"name": "Nine lives stealer", "cost": 23057, "url":"", "weight": {"minor": 0, "medium": 4, "major": 6} },
{"name": "Oathbow", "cost": 25600, "url":"", "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Sword of life stealing", "cost": 25715, "url":"", "weight": {"minor": 0, "medium": 2, "major": 4} },
{"name": "Mace of terror", "cost": 38552, "url":"", "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Life-drinker", "cost": 40320, "url":"", "weight": {"minor": 0, "medium": 0, "major": 6} },
{"name": "Sylvan scimitar", "cost": 47315, "url":"", "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Rapier of puncturing", "cost": 50320, "url":"", "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Sun blade", "cost": 50335, "url":"", "weight": {"minor": 0, "medium": 0, "major": 6} },
{"name": "Frost brand", "cost": 54475, "url":"", "weight": {"minor": 0, "medium": 0, "major": 6} },
{"name": "Dwarven thrower", "cost": 60312, "url":"", "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Luck blade (1 wish)", "cost": 62360, "url":"", "weight": {"minor": 0, "medium": 0, "major": 7} },
{"name": "Mace of smiting", "cost": 75312, "url":"", "weight": {"minor": 0, "medium": 0, "major": 4} },
{"name": "Luck blade (2 wishes)", "cost": 102660, "url":"", "weight": {"minor": 0, "medium": 0, "major": 2} },
{"name": "Holy avenger", "cost": 120630, "url":"", "weight": {"minor": 0, "medium": 0, "major": 1} },
{"name": "Luck blade (3 wishes)", "cost": 14296, "url":"", "weight": {"minor": 0, "medium": 0, "major": 1} }
],
"meleeSpecials" : [
{"name": "Bane of GET_BANE_TYPE", "bonus": 1, "weight": {"minor": 10, "medium": 6, "major": 3} },
{"name": "Defending", "bonus": 1, "weight": {"minor": 7, "medium": 6, "major": 0} },
{"name": "Flaming", "bonus": 1, "weight": {"minor": 10, "medium": 7, "major": 3} },
{"name": "Frost", "bonus": 1, "weight": {"minor": 10, "medium": 7, "major": 3} },
{"name": "Shock", "bonus": 1, "weight": {"minor": 10, "medium": 7, "major": 3} },
{"name": "Ghost touch", "bonus": 1, "weight": {"minor": 9, "medium": 5, "major": 3} },
{"name": "Keen", "bonus": 1, "weight": {"minor": 11, "medium": 6, "major": 0} },
{"name": "Ki Focus", "bonus": 1, "weight": {"minor": 4, "medium": 4, "major": 4} },
{"name": "Merciful", "bonus": 1, "weight": {"minor": 4, "medium": 2, "major": 0} },
{"name": "Mighty cleaving", "bonus": 1, "weight": {"minor": 7, "medium": 4, "major": 2} },
{"name": "Spell storing", "bonus": 1, "weight": {"minor": 5, "medium": 5, "major": 3} },
{"name": "Throwing", "bonus": 1, "weight": {"minor": 4, "medium": 4, "major": 4} },
{"name": "Thundering", "bonus": 1, "weight": {"minor": 4, "medium": 2, "major": 4} },
{"name": "Vicious", "bonus": 1, "weight": {"minor": 4, "medium": 4, "major": 4} },
{"name": "Anarchic", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Axiomatic", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Disruption", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 3} },
{"name": "Flaming burst", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Icy burst", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Holy", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Shocking burst", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Unholy", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Wounding", "bonus": 2, "weight": {"minor": 0, "medium": 2, "major": 4} },
{"name": "Speed", "bonus": 3, "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Brilliant energy", "bonus": 4, "weight": {"minor": 0, "medium": 0, "major": 3} },
{"name": "Dancing", "bonus": 4, "weight": {"minor": 0, "medium": 0, "major": 2} },
{"name": "Vorpal", "bonus": 5, "weight": {"minor": 0, "medium": 0, "major": 2} }
],
"rangedSpecials" : [
{"name": "Bane of GET_BANE_TYPE", "bonus": 1, "weight": {"minor": 12, "medium": 8, "major": 4} },
{"name": "Distance", "bonus": 1, "weight": {"minor": 13, "medium": 8, "major": 4} },
{"name": "Flaming", "bonus": 1, "weight": {"minor": 15, "medium": 12, "major": 4} },
{"name": "Frost", "bonus": 1, "weight": {"minor": 15, "medium": 12, "major": 4} },
{"name": "Merciful", "bonus": 1, "weight": {"minor": 5, "medium": 2, "major": 0} },
{"name": "Returning", "bonus": 1, "weight": {"minor": 8, "medium": 5, "major": 5} },
{"name": "Shock", "bonus": 1, "weight": {"minor": 5, "medium": 12, "major": 4} },
{"name": "Seeking", "bonus": 1, "weight": {"minor": 10, "medium": 5, "major": 2} },
{"name": "Thundering", "bonus": 1, "weight": {"minor": 6, "medium": 4, "major": 2} },
{"name": "Anarchic", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Axiomatic", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Flaming burst", "bonus": 2, "weight": {"minor": 0, "medium": 5, "major": 10} },
{"name": "Holy", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Icy burst", "bonus": 2, "weight": {"minor": 0, "medium": 5, "major": 10} },
{"name": "Shocking burst", "bonus": 2, "weight": {"minor": 0, "medium": 5, "major": 10} },
{"name": "Unholy", "bonus": 2, "weight": {"minor": 0, "medium": 3, "major": 5} },
{"name": "Speed", "bonus": 3, "weight": {"minor": 0, "medium": 0, "major": 5} },
{"name": "Brilliant energy", "bonus": 4, "weight": {"minor": 0, "medium": 0, "major": 6} }
]
}
+12 -12
View File
@@ -1,19 +1,19 @@
{
"data": {
"lawful": {
"good" : ["Erastil", "Iomedae", "Torag"],
"neutral" : ["Abadar", "Irori"],
"evil" : ["Asmodeus", "Zon-Kuthon"]
"Lawful": {
"Good" : ["Erastil", "Iomedae", "Torag"],
"Neutral" : ["Abadar", "Irori"],
"Evil" : ["Asmodeus", "Zon-Kuthon"]
},
"neutral": {
"good" : ["Sarenrae"],
"neutral" : ["Gozreh", "Pharasma", "Nethys"],
"evil" : ["Urgathoa", "Norgorber"]
"Neutral": {
"Good" : ["Sarenrae"],
"Neutral" : ["Gozreh", "Pharasma", "Nethys"],
"Evil" : ["Urgathoa", "Norgorber"]
},
"chaotic" : {
"good" : ["Desna", "Cayden Cailean"],
"neutral" : ["Gorum", "Calistria"],
"evil" : ["Lamashtu", "Rovagug"]
"Chaotic" : {
"Good" : ["Desna", "Cayden Cailean"],
"Neutral" : ["Gorum", "Calistria"],
"Evil" : ["Lamashtu", "Rovagug"]
}
}
}
+13
View File
@@ -0,0 +1,13 @@
[
{ "name": "Aquatic", "weight": 6},
{ "name": "Dwarf", "weight": 13},
{ "name": "Elf", "weight": 13},
{ "name": "Giant", "weight": 7},
{ "name": "Goblinoid", "weight": 6},
{ "name": "Gnoll", "weight": 7},
{ "name": "Gnome", "weight": 7},
{ "name": "Halfling", "weight": 8},
{ "name": "Human", "weight": 12},
{ "name": "Orc", "weight": 13},
{ "name": "Reptilian", "weight": 8}
]
+16
View File
@@ -0,0 +1,16 @@
[
{ "description": "Item can detect any special purpose foes within 60 feet",
"costMod": 10000, "egoMod": 1, "weight": 20 },
{ "description": "Item can cast GET_SPELL_LEVEL_4 at will",
"costMod": 56000, "egoMod": 2, "weight": 15 },
{"description": "Wielder gets +2 luck bonus on attacks, saves, and checks",
"costMod": 80000, "egoMod": 2, "weight": 15 },
{"description": "Item can cast GET_SPELL_LEVEL_5 at will",
"costMod": 90000, "egoMod": 2, "weight": 15 },
{"description": "Item can cast GET_SPELL_LEVEL_6 at will",
"costMod": 132000, "egoMod": 2, "weight": 25 },
{"description": "Item can cast GET_SPELL_LEVEL_7 at will",
"costMod": 182000, "egoMod": 2, "weight": 15 },
{"description": "Item can cast true resurrection on weilder, once per month",
"costMod": 200000, "egoMod": 2, "weight": 5 }
]
+32
View File
@@ -0,0 +1,32 @@
[
{"description": "Item can cast GET_SPELL_LEVEL_0 at will",
"costMod": 1000, "egoMod": 1, "repeatable": false, "weight": 10},
{"description": "Item can cast GET_SPELL_LEVEL_1 #/day",
"costMod": 1200, "egoMod": 1, "repeatable": true, "value": 3, "weight": 10},
{"description": "Item can use Magic Aura on itself at will",
"costMod": 2000, "egoMod": 1, "repeatable": false, "weight": 5},
{"description": "Item can cast GET_SPELL_LEVEL_2 #/day",
"costMod": 2400, "egoMod": 1, "repeatable": true, "value": 1, "weight": 10},
{"description": "Item has # ranks in GET_ITEM_SKILL",
"costMod": 2500, "egoMod": 1, "repeatable": true, "value": 5, "weight": 10},
{"description": "Item can sprout limbs and move with a speed of # feet",
"costMod": 5000, "egoMod": 1, "repeatable": true, "value": 10, "weight": 5},
{"description": "Item can cast GET_SPELL_LEVEL_3 #/day",
"costMod": 6000, "egoMod": 1, "repeatable": true, "value": 1, "weight": 5},
{"description": "Item can cast GET_SPELL_LEVEL_2 #/day",
"costMod": 1000, "egoMod": 1, "repeatable": true, "value": 3, "weight": 5},
{"description": "Item has # ranks in GET_ITEM_SKILL",
"costMod": 10000, "egoMod": 2, "repeatable": true, "value": 10, "weight": 10},
{"description": "Item can change shape into # other form(s) of the same size",
"costMod": 10000, "egoMod": 2, "repeatable": true, "value": 1, "weight": 5},
{"description": "Item can fly, as per the spell, at a speed of # feet",
"costMod": 10000, "egoMod": 2, "repeatable": true, "value": 30, "weight": 5},
{"description": "Item can cast GET_SPELL_LEVEL_4 #/day",
"costMod": 11200, "egoMod": 2, "repeatable": true, "value": 1, "weight": 5},
{"description": "Item can cast teleport itself #/day",
"costMod": 15000, "egoMod": 2, "repeatable": true, "value": 1, "weight": 5},
{"description": "Item can cast GET_SPELL_LEVEL_3 #/day",
"costMod": 18000, "egoMod": 2, "repeatable": true, "value": 3, "weight": 5},
{"description": "Item can cast GET_SPELL_LEVEL_4 #/day",
"costMod": 33600, "egoMod": 2, "repeatable": true, "value": 3, "weight": 5}
]
+15
View File
@@ -0,0 +1,15 @@
[
{"description": "Defeat/slay diametrically opposed alignment", "egoMod": 2, "weight": 20 },
{"description": "Defeat/slay arcane spellcasters (including spellcasting monsters and those that use spell-like abilities)",
"egoMod": 2, "weight": 10 },
{"description": "Defeat/slay divine spellcasters (including divine entities and servitors)",
"egoMod": 2, "weight": 10 },
{"description": "Defeat/slay non-spellcasters", "egoMod": 2, "weight": 10 },
{"description": "Defeat/slay all GET_BANE", "egoMod": 2, "weight": 5 },
{"description": "Defeat/slay all GET_HUMANOID_OR_OUTSIDER_TYPE", "egoMod": 2, "weight": 5 },
{"description": "Defend all GET_HUMANOID_OR_OUTSIDER_TYPE","egoMod": 2, "weight": 10 },
{"description": "Defeat/slay the servants of GET_DEITY", "egoMod": 2, "weight": 10 },
{"description": "Defend the servants of GET_DEITY", "egoMod": 2, "weight": 10 },
{"description": "Defeat/slay all (other than the item and the wielder)", "egoMod": 2, "weight": 5 },
{"description": "Make something up! (GM discression)", "egoMod": 2, "weight": 5 }
]
+22
View File
@@ -0,0 +1,22 @@
[
{ "name": "Appraise", "type": "intelligence" },
{ "name": "Knowledge (arcana)", "type": "intelligence" },
{ "name": "Knowledge (dungeoneering)", "type": "intelligence" },
{ "name": "Knowledge (engineering)", "type": "intelligence" },
{ "name": "Knowledge (geography)", "type": "intelligence" },
{ "name": "Knowledge (history)", "type": "intelligence" },
{ "name": "Knowledge (local)", "type": "intelligence" },
{ "name": "Knowledge (nature)", "type": "intelligence" },
{ "name": "Knowledge (nobility)", "type": "intelligence" },
{ "name": "Knowledge (planes)", "type": "intelligence" },
{ "name": "Knowledge (religion)", "type": "intelligence" },
{ "name": "Linguistics", "type": "intelligence" },
{ "name": "Spellcraft", "type": "intelligence" },
{ "name": "Bluff", "type": "charisma" },
{ "name": "Diplomacy", "type": "charisma" },
{ "name": "Intimidate", "type": "charisma" },
{ "name": "Perform", "type": "charisma" },
{ "name": "Perception", "type": "wisdom" },
{ "name": "Sense Motive", "type": "wisdom" },
{ "name": "Survival", "type": "wisdom" }
]
+23
View File
@@ -0,0 +1,23 @@
{
"data": [
"Abyssal",
"Aklo",
"Aquan",
"Auran",
"Celestial",
"Draconic",
"Dwarven",
"Elven",
"Giant",
"Gnome",
"Goblin",
"Gnoll",
"Halfling",
"Ignan",
"Infernal",
"Orc",
"Sylvan",
"Terran",
"Undercommon"
]
}
+11
View File
@@ -0,0 +1,11 @@
[
{ "name": "Air", "weight": 11},
{ "name": "Earth", "weight": 11},
{ "name": "Fire", "weight": 11},
{ "name": "Water", "weight": 11},
{ "name": "Chaotic", "weight": 11},
{ "name": "Evil", "weight": 11},
{ "name": "Good", "weight": 11},
{ "name": "Lawful", "weight": 11},
{ "name": "Native", "weight": 12}
]
+7
View File
@@ -0,0 +1,7 @@
{
"name": "Ultimate Combat",
"shortName": "UC",
"types": [
{"name": "Spells", "source": "sources/UC/Spells.json"}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"Arcane": [
["Haunted Fey Aspect"],
["Adjuring Step", "Abundant Ammunition", "Adoration", "Compel Hostility", "Deadeye's Lore", "Jury-Rig", "Liberating Command", "Lock Gaze", "Moment of Greatness", "Negative Reaction", "See Alignment", "Illusion of Calm", "Longshot", "Mirror Strike", "Reinforce Armaments", "Returning Weapon", "Shock Shield", "Unerring Weapon", "Warding Weapon", "Air Bubble", "Damp Powder", "Fabricate Bullets", "Peacebond", "Weaken Powder", "Life Conduit"],
["Blistering Invective", "Discovery Torch", "Pilfering Hand", "Qualm", "Returning Weapon", "Share Language, Communal", "Tactical Acumen", "Thunder Fire", "Adoration", "Animal Aspect", "Ant Haul, Communal", "Bestow Weapon Proficiency", "Brow Gasher", "Bullet Shield", "Certain Grip", "Destabilize Powder", "Endure Elements, Communal", "Fiery Shuriken", "Frost Fall", "Kinetic Reverberation", "Magic Siege Engine", "Mount, Communal", "Reloading Hands", "Protection from Chaos, Communal", "Protection from Evil, Communal", "Protection from Good, Communal", "Protection from Law, Communal", "Recoil Fire", "Reinforce Armaments, Communal", "Ricochet Shot", "Spontaneous Immolation", "Stabilize Powder", "Telekinetic Assembly", "Twisted Space", "Warding Weapon", "Ablative Barrier", "Mask Dweomer, Communal"],
["Delay Poison, Communal", "Phantom Driver", "Returning Weapon, Communal", "Tongues, Communal", "Ablative Barrier", "Animal Aspect", "Bestow Weapon Proficiency", "Brow Gasher", "Effortless Armor", "Mount, Communal", "Pilfering Hand", "Reloading Hands", "Reinforce Armaments, Communal", "Tactical Acumen", "Telekinetic Assembly", "Twisted Space", "Animal Aspect, Greater", "Burst of Speed", "Locate Weakness", "Chain of Perdition", "Darkvision, Communal", "Flash Fire", "Healing Thief", "Hostile Levitation", "Pellet Blast", "Protection from Arrows, Communal", "Pup Shape", "Resinous Skin", "Resist Energy, Communal", "Share Language, Communal", "Spider Climb, Communal", "Touch Injection", "Life Conduit, Improved", "Obsidian Flow", "Phantom Chariot", "Phantom Steed, Communal"],
["Phantom Steed, Communal", "Shocking Image", "Pellet Blast", "Wreath of Blades", "Animal Aspect, Greater", "Magic Siege Engine, Greater", "Named Bullet", "Nondetection, Communal", "Obsidian Flow", "Phantom Chariot", "Protection from Energy, Communal", "Telekinetic Charge", "Tongues, Communal", "Hostile Juxtaposition", "Stoneskin, Communal", "Summoner Conduit", "Absorb Toxicity", "Debilitating Portent"],
["Symbol of Striking", "Absorb Toxicity", "Energy Siege Shot", "Hostile Juxtaposition", "Stoneskin, Communal", "Summoner Conduit", "Wreath of Blades", "Life Conduit, Greater", "Tar Pool"],
["Walk through Space", "Energy Siege Shot, Greater", "Named Bullet, Greater", "Tar Pool", "Hostile Juxtaposition, Greater", "Dust Form"],
["Arcane Cannon", "Hostile Juxtaposition, Greater", "Walk through Space", "Walk through Space"],
["Frightful Aspect"],
["Heroic Invocation", "Mind Blank, Communal"]
],
"Divine": [
[],
["Abundant Ammunition", "Air Bubble", "Compel Hostility", "Deadeye's Lore", "Liberating Command", "Moment of Greatness", "Reinforce Armaments", "Sun Metal", "Damp Powder", "Weaken Powder", "Bowstaff", "Litany of Sloth", "Litany of Weakness", "Lock Gaze", "Longshot", "Peacebond", "Returning Weapon", "Unerring Weapon", "Tactical Acumen"],
["Ant Haul, Communal", "Bestow Weapon Proficiency", "Effortless Armor", "Endure Elements, Communal", "Instrument of Agony", "Magic Siege Engine", "Pilfering Hand", "Protection from Chaos, Communal", "Protection from Evil, Communal", "Protection from Good, Communal", "Protection from Law, Communal", "Reinforce Armaments, Communal", "Returning Weapon", "Animal Aspect", "Certain Grip", "Forest Friend", "Frost Fall", "Wilderness Soldiers", "Blistering Invective", "Brow Gasher", "Discovery Torch", "Litany of Defense", "Qualm", "Returning Weapon, Communal", "Tactical Acumen", "Divine Arrow", "Litany of Eloquence", "Litany of Entanglement", "Litany of Righteousness", "Litany of Warding", "Locate Weakness", "Reloading Hands", "Ricochet Shot"],
["Chain of Perdition", "Daybreak Arrow", "Deadly Juggernaut", "Delay Poison, Communal", "Discovery Torch", "Resist Energy, Communal", "Returning Weapon, Communal", "Share Language, Communal", "Animal Aspect, Greater", "Companion Mind Link", "Pup Shape", "Resinous Skin", "Spider Climb, Communal", "Burst of Speed", "Litany of Eloquence", "Litany of Entanglement", "Litany of Righteousness", "Litany of Warding", "Locate Weakness", "Litany of Escape", "Litany of Sight", "Named Bullet", "Protection from Energy, Communal"],
["Debilitating Portent", "Protection from Energy, Communal", "Summoner Conduit", "Water Walk, Communal", "Absorb Toxicity", "Obsidian Flow", "Find Quarry", "Judgment Light", "Litany of Escape", "Litany of Sight", "Magic Siege Engine, Greater", "Named Bullet", "Litany of Thunder", "Litany of Vengeance", "Darkvision, Communal", "Named Bullet, Greater", "Terrain Bond"],
["Air Walk, Communal", "Magic Siege Engine, Greater", "Spell Immunity, Communal", "Symbol of Striking", "Tongues, Communal", "Litany of Thunder", "Litany of Vengeance", "Stoneskin, Communal"],
["Dust Form", "Stoneskin, Communal", "Tar Pool", "Litany of Madness", "Named Bullet, Greater"],
["Jolting Portent", "Siege of Trees"],
["Frightful Aspect"],
["Spell Immunity, Greater Communal", "Siege of Trees, Greater"]
]
}
+5 -1
View File
@@ -10,6 +10,10 @@
"sources/Deities.json",
"sources/Humanoids.json",
"sources/Outsiders.json",
"sources/ItemSkills.json"
"sources/ItemSkills.json",
"sources/Languages.json",
"sources/ItemPowers.json",
"sources/ItemPurposes.json",
"sources/ItemDedicatedPowers.json"
]
}
+16
View File
@@ -0,0 +1,16 @@
Pathfinder magic item automatic roller
To do:
* Refactor code into GrimoireCore and resouce JSON objects
* Reformat all the .js data files into JSON resources
* Add roll weights for
= CRB
- Rings
= APG
- Rings
* I'm getting a problem where the random number generator is reliably getting the SAME item from a weighted list and I'm not sure why.
= This is occuring for getHumanoid, getOutsider, getDeity, and several other lowest level methods
when called from higher order functions like getIntelligence or getWeapon