mirror of
https://github.com/RussellChamp/GrimoireJS.git
synced 2026-10-27 22:42:32 +00:00
Revival of the GrimoireJS project
This commit is contained in:
1 parent
6845ce4a5f
commit
c190be3236
20 files changed
+3652
No files matched your search
+390
@@ -0,0 +1,390 @@
|
||||
/*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
|
||||
*/
|
||||
Reference in new issue
Block a user