We Need a Character Builder

It Does What It Says on the Tin: Resolved Issues

Moderators: Moderator, Developer, DM

Eclypticon
Posts: 1009
Joined: Mon May 30, 2011 7:26 pm
Location: USA

We Need a Character Builder

Unread post by Eclypticon »

Hello my good ladys and gents!

I'd like to point out that we need a text/html character builder. Nwn2db.com is not going to cut it forever. We have so much custom content now, that we could really use some help. This project is going to take a group of people working on it to achieve, and I am willing to help. I, however, do not know how to program html/java/php and the like.

The way I see it, we need a builder that works in html and can integrate with a database while being able to be exported into spreadsheets (and open source formats). Maybe something with forum integration.

I am willing to devote a large amount of my time into doing tedious entries, but I would require a patient mentor to work with me and guide me as programing is not my thing. We will also need someone that is already a team member or volunteer that knows about our custom content. We could also use an expert in toon building.

This is my suggestion today. Lets have a discussion. What do you folks say?
User avatar
Akroma666
Posts: 1888
Joined: Mon Jan 16, 2012 2:24 pm
Location: California

Re: We Need a Character Builder

Unread post by Akroma666 »

+92947474027838639101073747
Make this happen
Storm - The Blade Flurry
Druegar Grizzleclaw - The Mountain Ruin Tsar
Akroma Thuul - The Creepy Enchanter
Liliana Duskblade - The B*tch of Bane
Jamie Dawnbringer - The Light in the Darkness
User avatar
Young Werther
Posts: 863
Joined: Sat Sep 14, 2013 8:42 pm
Location: Azkaban

Re: We Need a Character Builder

Unread post by Young Werther »

Yes.... can anyone super smart say what would make this as easy as possible?
Lockonnow wrote:greatest fear like the movie Hellraiser they show you what you most fear and take a Image of IT
User avatar
Aspect of Sorrow
Custom Content
Posts: 2688
Joined: Fri Mar 28, 2014 7:11 pm
Location: Reliquary

Re: We Need a Character Builder

Unread post by Aspect of Sorrow »

Already underway. It taps into the game resource files and parses there rather than attempting to do so the way nwn2db performed it, that way the server updates automatically updates it. Not building it as a web front end at this time.

WinForms UI, so that Wine can use it fairly easily across Win/Mac/Linux. I don't have any mechanism behind export / user sharing right now but I'll worry on that later.
Last edited by Aspect of Sorrow on Wed Sep 07, 2016 10:02 pm, edited 2 times in total.
chad878262
Posts: 9332
Joined: Thu Sep 18, 2014 6:55 pm

Re: We Need a Character Builder

Unread post by chad878262 »

@AoS... You are seriously my hero man, don't ever change!
Chord Silverstrings - Bard and OSR Squire / Tarent Nefzen - Arcane Wand Merchant and Master Alchemist / Irrace Arkentlar - Drow Adventurer / Finneaus Du'Veil - Gem Merchant and Executive Officer of SCCE

Tarent's Wands and Elixirs

A Wand Crafter's guide to using wands
User avatar
Aspect of Sorrow
Custom Content
Posts: 2688
Joined: Fri Mar 28, 2014 7:11 pm
Location: Reliquary

Re: We Need a Character Builder

Unread post by Aspect of Sorrow »

It's just a 2da parser.
¯\_(ツ)_/¯
chad878262
Posts: 9332
Joined: Thu Sep 18, 2014 6:55 pm

Re: We Need a Character Builder

Unread post by chad878262 »

Aspect of Sorrow wrote:It's justa 2da parser. the coolest thing that we've needed for forever!
¯\_(ツ)_/¯
Fixed
Chord Silverstrings - Bard and OSR Squire / Tarent Nefzen - Arcane Wand Merchant and Master Alchemist / Irrace Arkentlar - Drow Adventurer / Finneaus Du'Veil - Gem Merchant and Executive Officer of SCCE

Tarent's Wands and Elixirs

A Wand Crafter's guide to using wands
Eclypticon
Posts: 1009
Joined: Mon May 30, 2011 7:26 pm
Location: USA

Re: We Need a Character Builder

Unread post by Eclypticon »

I was hoping that we might be able to use 2da's. We will still need some of the above mentioned additions. You are a real trouper AoS. Glad to have you aboard.

Anyone willing to work with AoS to do the front end?

Let me know if I can reasonably be of any help.
NegInfinity
Posts: 2449
Joined: Wed Feb 05, 2014 11:24 am

Re: We Need a Character Builder

Unread post by NegInfinity »

Eclypticon wrote: This is my suggestion today. Lets have a discussion. What do you folks say?
It is a fairly small project in C++/Qt 5. It could be done in... hmm... I'd say 2..4 weeks? And there will be a bit of debugging afterwards. The biggest problem would be handling feat dependencies. The whole thing can just blow up fairly quickly. Doesn't have to be qt, someone could go nuts and implement it as server-side python code or just html with few javascripts, but that might take more time.

The best way to make it happen would be to gather a bit of cash to get a programmer. Even if it is a "beer money" level of cash. Without monetory reward this kind of tool will take a year or two to develop due to lack of motivation (it'll be on/off development with starts and stops, etc).

Alternatively, you could ask nwn2db owners (assuming they aren't dead - the site hasn't been updated for a long time, as far as I know), if they would be willing to share their scripts or if they'd want to add bgtscc rules to their site.

That's pretty much it.
Last edited by NegInfinity on Wed Sep 07, 2016 10:52 pm, edited 1 time in total.
User avatar
Maecius
Retired Admin
Posts: 11639
Joined: Sat May 16, 2009 4:24 pm

Re: We Need a Character Builder

Unread post by Maecius »

Unfortunately, the admins over at nwn2db have basically given up the ghost, at least as far as the website's concerned (I was trying to get them to add BG:TSCC as a building option over the summer). But they have shared their source code with others in the community, and it's possible we can get it for ourselves if it would assist with fulfilling this request.

Let me know if you think this would help, AoS, and I can try and hunt it down. If not, we'll see what we can work out from your end!
NegInfinity
Posts: 2449
Joined: Wed Feb 05, 2014 11:24 am

Re: We Need a Character Builder

Unread post by NegInfinity »

Maecius wrote:Unfortunately, the admins over at nwn2db have basically given up the ghost, at least as far as the website's concerned (I was trying to get them to add BG:TSCC as a building option over the summer). But they have shared their source code with others in the community, and it's possible we can get it for ourselves if it would assist with fulfilling this request.

Let me know if you think this would help, AoS, and I can try and hunt it down. If not, we'll see what we can work out from your end!
In that case the best option would be to accquire nwn2db source code.
AlwaysSummer Day
Recognized Donor
Posts: 1170
Joined: Sun Jun 24, 2012 11:27 pm
Location: Detroit, Michigan

Re: We Need a Character Builder

Unread post by AlwaysSummer Day »

I had always hoped there would be a character building app for my cellphone. Bit of a pipedream I guess.
Roland; svirfneblin fist of the forest and eco terrorist.
Heinrich Von Rittermark; Everwatch Knights of Helm
Frederick Von Rittermark; Paladin of Azuth/Mystra
Erik Von Rittermark; Unknown
User avatar
Aspect of Sorrow
Custom Content
Posts: 2688
Joined: Fri Mar 28, 2014 7:11 pm
Location: Reliquary

Re: We Need a Character Builder

Unread post by Aspect of Sorrow »

The builder itself for nwn2db is entirely in javascript, your browser is downloading (ifnotcached) it every time you visit the site. The difference is that someone has to build the context (feats, classes, etc, probably just, you guessed it, parsing). It's php calls to sql for storage is easy thereafter.
User avatar
Aspect of Sorrow
Custom Content
Posts: 2688
Joined: Fri Mar 28, 2014 7:11 pm
Location: Reliquary

Re: We Need a Character Builder

Unread post by Aspect of Sorrow »

A few snippits of the nwn2db builder site, as much of the builder itself is in javascript.
I'm usually just against JS in general but this looks overkill, especially the hacky additions on Kaedrin's PRC.
Packbuilder.js
Hidden: show
builder.tick("Prototype Extensions");String.prototype.toTitleCase=function(){return this.replace(/([\w&`'��"�.@:\/\{\(\[<>_]+-? *)/g,function(b,d,a,c){if(a>0&&c.charAt(a-2)!==":"&&b.search(/^(a(nd?|s|t)?|b(ut|y)|en|for|i[fn]|o[fnr]|t(he|o)|vs?\.?|via)[ \-]/i)>-1){return b.toLowerCase()}if(c.substring(a-1,a+1).search(/['"_{(\[]/)>-1){return b.charAt(0)+b.charAt(1).toUpperCase()+b.substr(2)}if(b.substr(1).search(/[A-Z]+|&|[\w]+[._][\w]+/)>-1||c.substring(a-1,a+1).search(/[\])}]/)>-1){return b}return b.charAt(0).toUpperCase()+b.substr(1)})};String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};Array.prototype.find=function(c,e){if(e===undefined){for(var b=0;b<this.length;b++){if(this==c){return true}}}else{var b,a;var d=c.length;for(b=0;b<this.length;b++){for(a=0;a<d;a++){if(this==c[a]){return true}}}}return false};Array.prototype.high=function(){return Math.max.apply(Math,this)};Array.prototype.low=function(){return Math.min.apply(Math,this)};Array.prototype.fetch=function(c,b){for(var a in this){if(a==c){return this[a]}}return(b===undefined)?{}:b};builder.tick("Builder Constants");var MSIE=(jQuery.browser.msie)?jQuery.browser.version:0;builderConstants=function(){};builderConstants.prototype.BUILDER_TABLE_MIN_HEIGHT=750;builderConstants.prototype.ID_NONE=-1;builderConstants.prototype.CONFIG_DISPLAY_ICON=1;builderConstants.prototype.CONFIG_DISPLAY_TEXT=2;builderConstants.prototype.CONFIG_DEBUG_FEATS=0;builderConstants.prototype.CONFIG_DEBUG_RENDERER=1;builderConstants.prototype.GAME_VERSION_OC="oc";builderConstants.prototype.GAME_VERSION_MOTB="x1";builderConstants.prototype.GAME_VERSION_SOZ="x2";builderConstants.prototype.GAME_VERSION_MOW="x3";builderConstants.prototype.GAME_VERSION_KAEDRIN="kaedrin";builderConstants.prototype.GAME_VERSION_ROTE="rote";builderConstants.prototype.GAME_VERSION_ROTN="rotn";builderConstants.prototype.SCRIPT_SUMMARY_ATTACK=0;builderConstants.prototype.SCRIPT_SUMMARY_CASTER=1;builderConstants.prototype.SCRIPT_SUMMARY_AUTO_FEATS=2;builderConstants.prototype.SCRIPT_SUMMARY_CACHE_FEATS=3;builderConstants.prototype.APPLY_INVALID=0;builderConstants.prototype.APPLY_CURRENT=1;builderConstants.prototype.APPLY_NEXT=2;builderConstants.prototype.APPLY_RETROACTIVE=4;builderConstants.prototype.APPLY_ONLY_ONCE=8;builderConstants.prototype.OUTPUT_RAW=0;builderConstants.prototype.OUTPUT_DISPLAY=1;builderConstants.prototype.SKILL_TYPE_NON_CLASS=0;builderConstants.prototype.SKILL_TYPE_CLASS=1;builderConstants.prototype.SKILL_TYPE_CROSS_CLASS=2;builderConstants.prototype.DUAL_WIELD_MAIN_AB=-6;builderConstants.prototype.DUAL_WIELD_OFF_AB=-10;builderConstants.prototype.DUAL_WIELD_MOD_LIGHT=+2;builderConstants.prototype.SCOPE_BUILD=1;builderConstants.prototype.SCOPE_SKILLS=2;builderConstants.prototype.SCOPE_SPELLS=3;builderConstants.prototype.ABILITY_STR=0;builderConstants.prototype.ABILITY_DEX=1;builderConstants.prototype.ABILITY_CON=2;builderConstants.prototype.ABILITY_INT=3;builderConstants.prototype.ABILITY_WIS=4;builderConstants.prototype.ABILITY_CHA=5;builderConstants.prototype.SAVING_THROW_FORT=1;builderConstants.prototype.SAVING_THROW_REFL=2;builderConstants.prototype.SAVING_THROW_WILL=4;builderConstants.prototype.SAVING_THROW_DEATH=8;builderConstants.prototype.SAVING_THROW_MIND=16;builderConstants.prototype.SAVING_THROW_SPELL=32;builderConstants.prototype.SAVING_THROW_POISON=64;builderConstants.prototype.SAVING_THROW_FEAR=128;builderConstants.prototype.SAVING_THROW_DISEASE=256;builderConstants.prototype.SAVING_THROW_TRAPS=512;builderConstants.prototype.SCHOOL_GENERAL=0;builderConstants.prototype.SCHOOL_ABJURATION=1;builderConstants.prototype.SCHOOL_CONJURATION=2;builderConstants.prototype.SCHOOL_DIVINATION=3;builderConstants.prototype.SCHOOL_ENCHANTMENT=4;builderConstants.prototype.SCHOOL_EVOCATION=5;builderConstants.prototype.SCHOOL_ILLUSION=6;builderConstants.prototype.SCHOOL_NECROMANCY=7;builderConstants.prototype.SCHOOL_TRANSMUTATION=8;builderConstants.prototype.SCHOOL_INVOKER=9;builderConstants.prototype.SCHOOL_ALL=10;builderConstants.prototype.SCHOOL_SPECIALISATION=11;builderConstants.prototype.FEAT_TYPE_SUBSELECT=0;builderConstants.prototype.FEAT_TYPE_QUICK_TO_MASTER=1;builderConstants.prototype.FEAT_TYPE_BONUS=2;builderConstants.prototype.FEAT_TYPE_NORMAL=3;builderConstants.prototype.FEAT_TYPE_AUTO=4;builderConstants.prototype.FEAT_TYPE_ANY=5;builderConstants.prototype.FEAT_TYPE_COMBAT_STYLE=6;builderConstants.prototype.FEAT_TYPE_CASTABLE=7;builderConstants.prototype.SELECTOR_ABILITY=0;builderConstants.prototype.SELECTOR_FEAT=1;builderConstants.prototype.SELECTOR_DOMAIN=2;builderConstants.prototype.SELECTOR_SCHOOL=3;builderConstants.prototype.SELECTOR_FAMILIAR=4;builderConstants.prototype.SELECTOR_ANIMAL=5;builderConstants.prototype.SELECTOR_CLASS=6;builderConstants.prototype.SELECTOR_BACKGROUND=7;builderConstants.prototype.SELECTOR_ALIGNMENT=8;builderConstants.prototype.SELECTOR_RACE=9;builderConstants.prototype.SELECTOR_DEITY=10;builderConstants.prototype.SELECTOR_COMBAT_STYLE=11;builderConstants.prototype.SELECTOR_SKILLS=12;builderConstants.prototype.MENU_TYPE_FEATS=0;builderConstants.prototype.MENU_TYPE_CLASS=1;builderConstants.prototype.MENU_TYPE_SKILLS=2;builderConstants.prototype.CASTER_TYPE_NONE=-1;builderConstants.prototype.CASTER_TYPE_ARCANE=0;builderConstants.prototype.CASTER_TYPE_DIVINE=1;builderConstants.prototype.CASTER_TYPE_INVOKE=2;builderConstants.prototype.CASTER_TYPE_ANY=3;builderConstants.prototype.CASTER_TYPE_ALL=4;builderConstants.prototype.AFFECT_STR=1;builderConstants.prototype.AFFECT_DEX=2;builderConstants.prototype.AFFECT_CON=4;builderConstants.prototype.AFFECT_INT=8;builderConstants.prototype.AFFECT_WIS=16;builderConstants.prototype.AFFECT_CHA=32;builderConstants.prototype.AFFECT_SAVING_THROWS=64;builderConstants.prototype.AFFECT_CASTER_LEVEL=128;builderConstants.prototype.AFFECT_SPELL_LEVEL=256;builderConstants.prototype.AFFECT_BAB=512;builderConstants.prototype.AFFECT_HP=1024;builderConstants.prototype.AFFECT_RESISTANCE=2048;builderConstants.prototype.AFFECT_ARMOR=4096;builderConstants.prototype.AFFECT_ATTACK=8192;builderConstants.prototype.AFFECT_SPELL_DC=16384;builderConstants.prototype.AFFECT_SPELL_DC_BASE=32768;builderConstants.prototype.AFFECT_SKILLS=65536;builderConstants.prototype.AFFECT_REDUCTION=131072;builderConstants.prototype.AFFECT_SNEAK_ATTACK=262144;builderConstants.prototype.ALIGN_AXIS_LAWFUL_GOOD=1;builderConstants.prototype.ALIGN_AXIS_LAWFUL_NEUTRAL=2;builderConstants.prototype.ALIGN_AXIS_LAWFUL_EVIL=4;builderConstants.prototype.ALIGN_AXIS_NEUTRAL_GOOD=8;builderConstants.prototype.ALIGN_AXIS_NEUTRAL=16;builderConstants.prototype.ALIGN_AXIS_NEUTRAL_EVIL=32;builderConstants.prototype.ALIGN_AXIS_CHAOTIC_GOOD=64;builderConstants.prototype.ALIGN_AXIS_CHAOTIC_NEUTRAL=128;builderConstants.prototype.ALIGN_AXIS_CHAOTIC_EVIL=256;builderConstants.prototype.ALIGN_AXIS_GOOD=(1|8|64);builderConstants.prototype.ALIGN_AXIS_EVIL=(4|32|256);builderConstants.prototype.ALIGN_AXIS_LAWFUL=(1|2|4);builderConstants.prototype.ALIGN_AXIS_CHAOTIC=(64|128|256);builderConstants.prototype.FIELD_INDEX_DEITY_FULLNAME=40;builderConstants.prototype.FIELD_INDEX_ALIGNMENT_ICON=2;builderConstants.prototype.ARMOR_TYPE_NATURAL=1;builderConstants.prototype.ARMOR_TYPE_AC=2;builderConstants.prototype.ARMOR_TYPE_DODGE=4;builderConstants.prototype.ARMOR_TYPE_SHIELD=8;builderConstants.prototype.ARMOR_TYPE_DEFLECTION=16;builderConstants.prototype.ARMOR_TYPE_DEXTERITY=32;builderConstants.prototype.ARMOR_NONE=1;builderConstants.prototype.ARMOR_LIGHT=2;builderConstants.prototype.ARMOR_MEDIUM=4;builderConstants.prototype.ARMOR_HEAVY=8;builderConstants.prototype.ARMOR_SHIELD_LIGHT=16;builderConstants.prototype.ARMOR_SHIELD_HEAVY=32;builderConstants.prototype.ARMOR_SHIELD_TOWER=64;builderConstants.prototype.ARMOR_GROUP_NO_SHIELD=(1|2|4|8);builderConstants.prototype.ENEMY_ANY=1;builderConstants.prototype.ENEMY_FAVORED=2;builderConstants.prototype.ENEMY_CRITICAL=4;builderConstants.prototype.MOVEMENT_ANY=1;builderConstants.prototype.MOVEMENT_OUTDOORS=2;builderConstants.prototype.MOVEMENT_INDOORS=4;builderConstants.prototype.MOVEMENT_STEALTH=8;builderConstants.prototype.ENVIRONMENT_ANY=1;builderConstants.prototype.ENVIRONMENT_INDOORS=2;builderConstants.prototype.ENVIRONMENT_OUTDOORS=3;builderConstants.prototype.CONDITION_ABILITY=1;builderConstants.prototype.CONDITION_CLASS_LEVEL=2;builderConstants.prototype.RESIST_TYPE_ACID=1;builderConstants.prototype.RESIST_TYPE_COLD=2;builderConstants.prototype.RESIST_TYPE_CRITICAL=4;builderConstants.prototype.RESIST_TYPE_DISEASE=8;builderConstants.prototype.RESIST_TYPE_ELECTRICAL=16;builderConstants.prototype.RESIST_TYPE_FEAR=32;builderConstants.prototype.RESIST_TYPE_FIRE=64;builderConstants.prototype.RESIST_TYPE_HOLD=128;builderConstants.prototype.RESIST_TYPE_MIND=256;builderConstants.prototype.RESIST_TYPE_PARALYSIS=512;builderConstants.prototype.RESIST_TYPE_POISON=1024;builderConstants.prototype.RESIST_TYPE_SLEEP=2048;builderConstants.prototype.RESIST_TYPE_SONIC=5096;builderConstants.prototype.RESIST_TYPE_SPELL=10192;builderConstants.prototype.RESIST_TYPE_STUN=20384;builderConstants.prototype.RESIST_TYPE_DEATH=40768;builderConstants.prototype.RESIST_TYPE_ABILITY_DRAIN=81536;builderConstants.prototype.RESIST_TYPE_ENERGY_DRAIN=163072;builderConstants.prototype.RESIST_TYPE_CHARM=326144;builderConstants.prototype.RESIST_TYPE_DOMINATE=652288;builderConstants.prototype.RESIST_TYPE_CRITICAL=1304576;builderConstants.prototype.RESIST_TYPE_SNEAK=2609152;builderConstants.prototype.RESIST_IMMUNE=-1;builderConstants.prototype.STACK_ALL=0;builderConstants.prototype.STACK_FEATS=1;builderConstants.prototype.STACK_SPELLS=2;builderConstants.prototype.STACK_ITEMS=3;builderConstants.prototype.STACK_NONE=4;builderConstants.prototype.REDUCTION_NONE=1;builderConstants.prototype.REDUCTION_COLD_IRON=2;builderConstants.prototype.REDUCTION_SILVER=4;builderConstants.prototype.REDUCTION_MAGIC=8;builderConstants.prototype.REDUCTION_PHYSICAL=16;builderConstants.prototype.SKILL_CONCENTRATION=1;builderConstants.prototype.SKILL_DISARM=2;builderConstants.prototype.SKILL_HEAL=4;builderConstants.prototype.SKILL_HIDE=5;builderConstants.prototype.SKILL_LISTEN=6;builderConstants.prototype.SKILL_LORE=7;builderConstants.prototype.SKILL_MOVE=8;builderConstants.prototype.SKILL_OPEN=9;builderConstants.prototype.SKILL_PARRY=10;builderConstants.prototype.SKILL_PERFORM=11;builderConstants.prototype.SKILL_DIPLOMACY=12;builderConstants.prototype.SKILL_HAND=13;builderConstants.prototype.SKILL_SEARCH=14;builderConstants.prototype.SKILL_TRAP=15;builderConstants.prototype.SKILL_SPELLCRAFT=16;builderConstants.prototype.SKILL_SPOT=17;builderConstants.prototype.SKILL_TAUNT=18;builderConstants.prototype.SKILL_USE_MAGIC=19;builderConstants.prototype.SKILL_APPRAISE=20;builderConstants.prototype.SKILL_TUMBLE=21;builderConstants.prototype.SKILL_CRAFT_TRAP=22;builderConstants.prototype.SKILL_BLUFF=23;builderConstants.prototype.SKILL_INTIMIDATE=24;builderConstants.prototype.SKILL_CRAFT_ARMOR=25;builderConstants.prototype.SKILL_CRAFT_WEAPON=26;builderConstants.prototype.SKILL_CRAFT_ALCHEMY=27;builderConstants.prototype.SKILL_SURVIVAL=29;builderConstants.prototype.RULE_TYPE_BACKGROUND=1;builderConstants.prototype.RULE_TYPE_FEAT=2;builderConstants.prototype.WEAPON_OF_CHOICE=-3;builderConstants.prototype.WEAPON_ANY=-2;builderConstants.prototype.WEAPON_UNARMED=-1;builderConstants.prototype.WEAPON_TYPES_MELEE=[];builderConstants.prototype.WEAPON_TYPES_MELEE_TOUCH=[];builderConstants.prototype.WEAPON_TYPES_RANGED=[];builderConstants.prototype.WEAPON_TYPES_RANGED_TOUCH=[];builderConstants.prototype.THREAT_DOUBLED=1;builderConstants.prototype.WEAPON_HAND_MAIN=1;builderConstants.prototype.WEAPON_HAND_OFF=2;builderConstants.prototype.WEAPON_HAND_RANGED=4;builderConstants.prototype.WEAPON_HAND_TOUCH_MELEE=8;builderConstants.prototype.WEAPON_HAND_TOUCH_RANGED=16;builderConstants.prototype.WEAPON_HAND_DUAL=(1|3);builderConstants.prototype.WEAPON_HAND_ANY=(1|2|4|8|16);builderConstants.prototype.WEAPON_ATTACK_TYPE_NORMAL=1;builderConstants.prototype.WEAPON_ATTACK_TYPE_ENCHANTED=2;builderConstants.prototype.WEAPON_ATTACK_TYPE_MAGIC=4;builderConstants.prototype.WEAPON_ATTACK_TYPE_LAWFUL=8;builderConstants.prototype.WEAPON_ATTACK_TYPE_ADAMANTINE=16;builderConstants.prototype.WEAPON_TYPE_NONE=1;builderConstants.prototype.WEAPON_TYPE_PIERCING=2;builderConstants.prototype.WEAPON_TYPE_BLUDGEONING=4;builderConstants.prototype.WEAPON_TYPE_SLASHING=8;builderConstants.prototype.WEAPON_TYPE_LIGHT=16;builderConstants.prototype.WEAPON_TYPE_MEDIUM=32;builderConstants.prototype.WEAPON_TYPE_HEAVY=64;builderConstants.prototype.HISTORY_SCOPE_RACE=1;builderConstants.prototype.HISTORY_SCOPE_ABILITY=2;builderConstants.prototype.HISTORY_SCOPE_ALIGNMENT=3;builderConstants.prototype.HISTORY_SCOPE_BACKGROUND=4;builderConstants.prototype.HISTORY_SCOPE_DEITY=5;builderConstants.prototype.HISTORY_SCOPE_FAMILIAR=6;builderConstants.prototype.HISTORY_SCOPE_ANIMAL=7;builderConstants.prototype.HISTORY_SCOPE_DOMAIN=8;builderConstants.prototype.HISTORY_SCOPE_CLASS=9;builderConstants.prototype.HISTORY_SCOPE_CLASS_BATCH=10;builderConstants.prototype.HISTORY_SCOPE_FEAT=11;builderConstants.prototype.HISTORY_SCOPE_SCHOOL=12;builder.constant=new builderConstants();builder.tick("2DA Data Storage");builder.data={_store:[]};var dataTable=function(){};dataTable.prototype.ID_NONE=builder.constant.ID_NONE;dataTable.prototype.fields=[];dataTable.prototype.data=[];dataTable.prototype.rowData=false;dataTable.prototype.rowValid=false;dataTable.prototype.table=function(a){if(!builder.data._store[a]){builder.log("error",'Failed to read "'+a+'" 2da table');this.fields=[];this.data=[];this.rowData=false;return this}this.fields=builder.data._store[a].h;this.data=builder.data._store[a].d;this.rowData=false;return this};dataTable.prototype.row=function(c,a){this.rowData=[];if(a!==undefined){if(this.data[a]!==undefined){this.rowData=this.data[a]}}else{if(c==this.ID_NONE){return this}var b=this.data.length;while(b--){if(this.data[0]==c){this.rowData=this.data;break}}}this.rowValid=(this.rowData.length)?true:false;return this};dataTable.prototype.field=function(c,b){if(!this.rowData){return(b===undefined)?this.ID_NONE:b}var a=this.fields.length;while(a--){if(this.fields[a]==c){return this.rowData[a]}}return(b===undefined)?this.ID_NONE:b};builder.tick("Output Generator");var builderOutput=function(){};builderOutput.prototype.pause=true;builderOutput.prototype._cache=[];builderOutput.prototype.template=[];builderOutput.prototype.colours=[];builderOutput.prototype.initialise=function(){this.template.build_table();this.template.skills_table();this.template.stats_frame();this.template.abilities_table();this.template.utilities_bar();this.template.build_info()};builderOutput.prototype.findColour=function(c){var b;var a=this.colours.length;for(b=0;b<a;b++){if(this.colours==c){return"class"+(b+1)}}return"class0"};builderOutput.prototype.assignColours=function(){var a=builder.rules;var g=builder.build;var e=[];var d,f;var b=a.max_level;this.colours=[];var c=0;for(d=1;d<=b;d++){f=g.level[d].class_id;if(e.find(f)){continue}e.push(f);this.colours[c]=f;c++;if(c>=4){break}}};builderOutput.prototype.update=function(){var f=builder.constant;var j=builder.rules;var d=[];switch(build.scope){case f.SCOPE_BUILD:d=this.update_build();break;case f.SCOPE_SKILLS:d=this.update_skills();break}var c=0;var g,h,a;var e=d.length;while(e--){g=d[e].object;if(d[e].className!==undefined){a=true;h=d[e].className}else{a=false;h=(d[e].icon)?d[e].icon:d[e].value}if(this._cache[g]!==undefined){if(this._cache[g]===h){c++;continue}}if(a){$(g).attr("class",h)}else{if(d[e].icon){if(d[e].size===undefined){d[e].size=40}var l=(d[e].size)?d[e].size+"x"+d[e].size+"/":"";var b=builder.directory.icons+l+d[e].icon+".png";$(g).css("background-image","url("+b+")")}else{$(g).html(h)}}this._cache[g]=h}if(build.scope==f.SCOPE_SKILLS){var k=j.max_level;for(var e=1;e<=k;e++){$("#skill_level_"+e+" .skill_frame").each(function(n){var m=e;$(this).unbind("click").unbind("contextmenu");$(this).bind("click",function(o){switch(true){case (o.ctrlKey&&o.shiftKey):build.skills.increaseMax(n,m,true);break;case (o.ctrlKey):build.skills.decrease(n,m);break;case (o.shiftKey):build.skills.increaseMax(n,m,false);break;default:build.skills.increase(n,m)}return false}).bind("contextmenu",function(o){switch(true){case (o.shiftKey):build.skills.decreaseMax(n,m);break;default:build.skills.decrease(n,m)}return false})})}}$(".level_spacer").css("height",0).hide();$(".level_spacer").css("height",f.BUILDER_TABLE_MIN_HEIGHT-$("#build").height()).show();if(builder.debug){_END_DATE=new Date();builder.log("update","["+build.scope+"] Rendered "+d.length+" elements in "+((_END_DATE.getTime()-_START_DATE.getTime())/1000)+"ms ("+c+" cached)",1)}builder.makeTitles();builder.ui.draggableFeats()};builderOutput.prototype.update_header=function(g){var c=builder.constant;var a=builder.rules;var f=builder.summary;var d=builder.build;var b=a.max_level;if(build.skills.validate()==false){if(!$("#output_utilities .skills span .invalid").length){$("#output_utilities .skills span").append('<span class="invalid">&nbsp;</span>')}}else{$("#output_utilities .skills span .invalid").remove()}g.push({object:"#output_stats .race .label",value:d.race.label});g.push({object:"#output_stats .race .icon",value:false,size:40,icon:d.race.icon});g.push({object:"#output_stats .alignment .label",value:d.alignment.label+build.alignment.validate().output()});g.push({object:"#output_stats .alignment .icon",value:false,size:40,icon:d.alignment.icon});g.push({object:"#output_stats .deity .label",value:d.deity.label+build.deity.validate(d.deity.id).output()});g.push({object:"#output_stats .deity .icon",value:false,size:40,icon:d.deity.icon});g.push({object:"#output_stats .background .label",value:d.background.label+build.background.validate(d.background.id).output()});g.push({object:"#output_stats .background .icon",value:false,size:40,icon:d.background.icon});var e=f.abilities.fetch(1,c.FEAT_TYPE_AUTO);g.push({object:"#ability_STR",value:e[c.ABILITY_STR].value});g.push({object:"#ability_DEX",value:e[c.ABILITY_DEX].value});g.push({object:"#ability_CON",value:e[c.ABILITY_CON].value});g.push({object:"#ability_INT",value:e[c.ABILITY_INT].value});g.push({object:"#ability_WIS",value:e[c.ABILITY_WIS].value});g.push({object:"#ability_CHA",value:e[c.ABILITY_CHA].value});e=f.abilities.fetch(b);g.push({object:"#final_STR",value:e[c.ABILITY_STR].value});g.push({object:"#final_DEX",value:e[c.ABILITY_DEX].value});g.push({object:"#final_CON",value:e[c.ABILITY_CON].value});g.push({object:"#final_INT",value:e[c.ABILITY_INT].value});g.push({object:"#final_WIS",value:e[c.ABILITY_WIS].value});g.push({object:"#final_CHA",value:e[c.ABILITY_CHA].value});g.push({object:"#mod_STR",value:e[c.ABILITY_STR].modifier});g.push({object:"#mod_DEX",value:e[c.ABILITY_DEX].modifier});g.push({object:"#mod_CON",value:e[c.ABILITY_CON].modifier});g.push({object:"#mod_INT",value:e[c.ABILITY_INT].modifier});g.push({object:"#mod_WIS",value:e[c.ABILITY_WIS].modifier});g.push({object:"#mod_CHA",value:e[c.ABILITY_CHA].modifier});return g};builderOutput.prototype.update_build=function(){var w=builder.constant;var m=builder.rules;var l=builder.summary;var y=builder.build;var g=[];var u,s;var t=m.max_level;if(builder.debug){_START_DATE=new Date()}this.assignColours();this.update_header(g);var o,b,a,h,p,d,n,q=[],f=(builder.game_version=="rote"||builder.game_version=="rotn"),x=(builder.game_version=="rote");for(u=1;u<=t;u++){o=y.level.class_id;b=builder.classLevel(u,o);h=y.level.class_label;a=this.findColour(o);g.push({object:"#level_"+u,className:(u==t)?a+" last":a});g.push({object:"#class_"+u,value:'<span class="level_no" onclick="builder.menu.show(event,'+w.MENU_TYPE_CLASS+","+u+');return false;">'+u+'</span><span class="class_level_no">'+b+"</span>"+h+build.classes.validate(o,false,u).output()});g.push({object:"#options_"+u,value:this.classOptions(u)});g.push({object:"#str_"+u,value:this.abilitySelector(w.ABILITY_STR,u)});g.push({object:"#dex_"+u,value:this.abilitySelector(w.ABILITY_DEX,u)});g.push({object:"#con_"+u,value:this.abilitySelector(w.ABILITY_CON,u)});g.push({object:"#int_"+u,value:this.abilitySelector(w.ABILITY_INT,u)});g.push({object:"#wis_"+u,value:this.abilitySelector(w.ABILITY_WIS,u)});g.push({object:"#cha_"+u,value:this.abilitySelector(w.ABILITY_CHA,u)});n=l.bab.fetch(u,w.FEAT_TYPE_ANY);g.push({object:"#bab_"+u,value:"+"+n.value});d=l.saves.fetch(u,w.FEAT_TYPE_ANY);g.push({object:"#fort_"+u,value:d[w.SAVING_THROW_FORT].value});g.push({object:"#refl_"+u,value:d[w.SAVING_THROW_REFL].value});g.push({object:"#will_"+u,value:d[w.SAVING_THROW_WILL].value});g.push({object:"#feats_"+u,value:this.featSelectors(u)});g.push({object:"#extra_"+u,value:this.featExtra(u,q)});if(x&&u==1){var e,r,v,c;for(s=1;s<=4;s++){v=y.ability.ROTE||[0,0,0,0,0,0];g.push({object:"#rote_extra_ability_str",value:this.abilitySelectorROTE(w.ABILITY_STR,u)});g.push({object:"#rote_extra_ability_dex",value:this.abilitySelectorROTE(w.ABILITY_DEX,u)});g.push({object:"#rote_extra_ability_con",value:this.abilitySelectorROTE(w.ABILITY_CON,u)});g.push({object:"#rote_extra_ability_int",value:this.abilitySelectorROTE(w.ABILITY_INT,u)});g.push({object:"#rote_extra_ability_wis",value:this.abilitySelectorROTE(w.ABILITY_WIS,u)});g.push({object:"#rote_extra_ability_cha",value:this.abilitySelectorROTE(w.ABILITY_CHA,u)});e=0;r=6;while(r--){e+=v[r]}c=(m.rot_epic_relevel_points-e);g.push({object:"#rote_extra_ability_points",value:c+' Ability Points Remaining &nbsp;&nbsp;&nbsp;(<a style="float:none;display:inline;cursor:pointer;color:#fff;" onclick="builder.ui.resetROTExtraAbilities(event);"> reset </a>)'});g.push({object:"#rote_extra_ability",className:(u==t)?a+" last":a})}}if(f&&u==m.rot_epic_relevel){var e,r,v,c;for(s=1;s<=4;s++){v=y.ability.ROT[s];g.push({object:"#epic_relevel_"+s+"_str",value:this.abilitySelectorROT(w.ABILITY_STR,u,s)});g.push({object:"#epic_relevel_"+s+"_dex",value:this.abilitySelectorROT(w.ABILITY_DEX,u,s)});g.push({object:"#epic_relevel_"+s+"_con",value:this.abilitySelectorROT(w.ABILITY_CON,u,s)});g.push({object:"#epic_relevel_"+s+"_int",value:this.abilitySelectorROT(w.ABILITY_INT,u,s)});g.push({object:"#epic_relevel_"+s+"_wis",value:this.abilitySelectorROT(w.ABILITY_WIS,u,s)});g.push({object:"#epic_relevel_"+s+"_cha",value:this.abilitySelectorROT(w.ABILITY_CHA,u,s)});e=0;r=6;while(r--){e+=v[r]}c=(m.rot_epic_relevel_points-e);g.push({object:"#epic_relevel_"+s+"_points",value:c+' Ability Points Remaining &nbsp;&nbsp;&nbsp;(<a style="float:none;display:inline;cursor:pointer;color:#fff;" onclick="builder.ui.resetEpicRelevel(event,'+s+');"> reset </a>)'});g.push({object:"#relevel_"+s,className:(u==t)?a+" last":a})}}}g.push({object:".level_spacer",className:"level_spacer "+a});return g};builderOutput.prototype.update_skills=function(){var s=builder.constant;var h=builder.rules;var g=builder.summary;var t=builder.build;var e=[];var r,p;var q=h.max_level;if(builder.debug){_START_DATE=new Date()}this.update_header(e);var c=t.skills.length;var u="";$("#output_utilities .skills span .invalid").remove();if(c==0){e.push({object:"#skill_expand",value:'<a id="skills_choose" onclick="builder.selector.generic.open('+s.SELECTOR_SKILLS+');return false;"></a><span>Click to add a new skill column</span>'})}else{u="";for(p=0;p<c;p++){u+='<a title="skill:'+t.skills[p].id+'" class="skills_icon" data-index="'+p+'"style="background-image:url('+builder.directory.icons+"40x40/"+t.skills[p].icon+'.png);"onclick="builder.menu.show(event,'+s.MENU_TYPE_SKILLS+');"><span class="icon_menu"></span></a>'}u+='<a id="skills_choose" onclick="builder.selector.generic.open('+s.SELECTOR_SKILLS+');return false;"></a>';e.push({object:"#skill_expand",value:u})}e.push({object:"#skill_total",value:build.skills.unused()});var k,b,f,a;var l,m,w,o,d;var n=[];var v=[];u="";for(r=1;r<=q;r++){k=t.level[r].class_id;b=builder.classLevel(r,k);f=t.level[r].class_label;a=this.findColour(k);d=(r==q)?a+" last":a;if(build.skills.free(r)<0){d+=" invalid"}e.push({object:"#skill_level_"+r,className:d});e.push({object:"#skill_level_"+r+" .class",value:'<span class="level_no no_hover">'+r+'</span><span class="class_level_no no_hover">'+b+"</span>"+f+build.classes.validate(k,false,r,true).output()});e.push({object:"#skill_gain_"+r,value:"+"+build.skills.gain(r)});e.push({object:"#skill_saved_"+r,value:build.skills.saved(r)});e.push({object:"#skill_total_"+r,value:build.skills.free(r)});u="";for(p=0;p<c;p++){if(v[p]===undefined){v[p]=0}o=(build.skills.skill_type(p,r)==s.SKILL_TYPE_CLASS)?"":" cross_class";m=t.skills[p].points[r];v[p]+=m;if(m){u+='<div class="unselectable skill_frame'+o+'">'+v[p]+"</div>"}else{u+='<div class="unselectable skill_frame skill_none'+o+'">'+v[p]+"</div>"}}if(t.skills.length<=5){switch(r){case 2:u+='<span class="instruction">Click a skill icon to view the skill options menu</span>';break;case 4:u+='<span class="instruction"><strong>Left Click</strong> on a skill box to increase the skill points</span>';break;case 5:u+='<span class="instruction"><strong>Right Click (or Ctrl + Left Click)</strong> to decrease the skill points</span>';break;case 7:u+='<span class="instruction"><strong>Shift + Left Click</strong> to max skill points from that level up</span>';break;case 8:u+='<span class="instruction"><strong>Shift + Right Click</strong> to clear skill points from that level down</span>';break;case 9:u+='<span class="instruction"><strong>Shift + Ctrl + Left Click</strong> to max on single-cost levels only</span>';break}}e.push({object:"#skill_values_"+r,value:u})}e.push({object:".level_spacer",className:"level_spacer "+a});return e};builderOutput.prototype.classOptions=function(c){var k=builder.constant;var r=builder.rules;var q=builder.summary;var m=builder.build;var h=(new dataTable()).table("classes").row(m.level[c].class_id);var f=m.level[c].class_id;var e=builder.classLevel(c,f);var d="";var j=1;var p,n;var o=builder.directory.icons;if(e==1){if(h.field("hasdomains",0)){for(var g=0;g<m.domain.length;g++){p=(m.domain[g].id!=k.ID_NONE)?m.domain[g].label:"Select Domain";n=(m.domain[g].id!=k.ID_NONE)?o+"16x16/"+m.domain[g].icon:false;n=(n!==false)?'<span class="icon" style="background-image:url('+n+'.png)"></span>':"";d+='<a class="option'+(m.domain[g].id!=k.ID_NONE?"":" empty")+'" id="option_'+(j++)+"_"+c+'" onclick="builder.selector.generic.open('+k.SELECTOR_DOMAIN+","+c+","+g+');">'+n+p+"</a>"}}if(h.field("hasschool",0)){p=(m.school.id!=k.ID_NONE)?m.school.label:"Select School";n=(m.school.id!=k.ID_NONE)?o+"16x16/"+m.school.icon:false;n=(n!==false)?'<span class="icon" style="background-image:url('+n+'.png)"></span>':"";d+='<a class="option'+(m.school.id!=k.ID_NONE?"":" empty")+'" id="option_'+(j++)+"_"+c+'" onclick="builder.selector.generic.open('+k.SELECTOR_SCHOOL+","+c+');">'+n+p+"</a>"}}if(h.field("hasfamiliar",0)&&q.feats.have(303,c,k.FEAT_TYPE_ANY,true)){var l=(m.familiar[f]!==undefined)?m.familiar[f].id:k.ID_NONE;p=(l!=k.ID_NONE)?m.familiar[f].label:"Select Familiar";n=(l!=k.ID_NONE)?o+"16x16/"+m.familiar[f].icon:false;n=(n!==false)?'<span class="icon" style="background-image:url('+n+'.png)"></span>':"";d+='<a class="option'+(l!=k.ID_NONE?"":" empty")+'" id="option_'+(j++)+"_"+c+'" onclick="builder.selector.generic.open('+k.SELECTOR_FAMILIAR+","+c+');">'+n+p+"</a>"}if(h.field("hasanimalcompanion",0)&&q.feats.have(199,c,k.FEAT_TYPE_ANY,true)){var b=(m.animal[f]!==undefined)?m.animal[f].id:k.ID_NONE;p=(b!=k.ID_NONE)?m.animal[f].label:"Select Animal";if(b!=k.ID_NONE){p+=build.animal.validate(b,c).output()}n=(b!=k.ID_NONE)?o+"16x16/"+m.animal[f].icon:false;n=(n!==false)?'<span class="icon" style="background-image:url('+n+'.png)"></span>':"";d+='<a class="option'+(b!=k.ID_NONE?"":" empty")+'" id="option_'+(j++)+"_"+c+'" onclick="builder.selector.generic.open('+k.SELECTOR_ANIMAL+","+c+');">'+n+p+"</a>"}if(f==7&&e==2){var a=build.feat.get(k.FEAT_TYPE_COMBAT_STYLE,c);switch(a.id){case k.ID_NONE:n=false;p="Select Combat Style";break;case 1729:n=(new dataTable()).table("feat").row(1729).field("icon");p="Two-Weapon Style";break;case 1730:n=(new dataTable()).table("feat").row(1730).field("icon");p="Archery Style";break;case 3887:n=(new dataTable()).table("feat").row(3887).field("icon");p="Two-Handed Style";break}n=(n!==false)?'<span class="icon" style="background-image:url('+o+"16x16/"+n+'.png)"></span>':"";d+='<a class="option'+(a.id!=k.ID_NONE?"":" empty")+'" id="option_'+(j++)+"_"+c+'" onclick="builder.selector.generic.open('+k.SELECTOR_COMBAT_STYLE+","+c+');">'+n+p+"</a>"}return d};builderOutput.prototype.abilitySelector=function(f,a){var e=builder.constant;var j=builder.rules;var h=builder.summary;var g=builder.build;var d=h.abilities.fetch(a,e.FEAT_TYPE_ANY);if(a==1){return'<a class="display">'+d[f].value+"</a>"}if(!j.ability_selection.find(a)){var b=h.abilities.fetch(a-1,e.FEAT_TYPE_ANY);return(d[f].value!=b[f].value)?'<a class="display">'+d[f].value+"</a>":"&nbsp;"}var c=(g.level[a].ability==f)?" selected":"";var k='onclick="builder.ui.clickAbility(event,'+a+","+f+');"';return'<a class="select'+c+'" '+k+">"+d[f].value+"</a>"};builderOutput.prototype.abilitySelectorROT=function(f,a,e){var d=builder.constant;var l=builder.rules;var k=builder.summary;var g=builder.build;var h=g.ability.ROT[e]||[0,0,0,0,0,0],c=parseInt(h[f])||0;var b=(c>0)?" selected":"";var j="";switch(f){case d.ABILITY_STR:j="Strength";break;case d.ABILITY_DEX:j="Dexterity";break;case d.ABILITY_CON:j="Constitution";break;case d.ABILITY_INT:j="Intelligence";break;case d.ABILITY_WIS:j="Wisdom";break;case d.ABILITY_CHA:j="Charisma";break}if(c>0){j+=" +"+c}var m='onclick="builder.ui.clickEpicRelevel(event,'+e+","+f+');"';return'<a title="'+j+'" style="font-family:arial,serif;" class="select'+b+'" '+m+">"+(c>0?"+":"")+c+"</a>"};builderOutput.prototype.abilitySelectorROTE=function(e,a){var c=builder.constant;var k=builder.rules;var j=builder.summary;var f=builder.build;var g=f.ability.ROTE||[0,0,0,0,0,0],d=parseInt(g[e])||0;var b=(d>0)?" selected":"";var h="";switch(e){case c.ABILITY_STR:h="Strength";break;case c.ABILITY_DEX:h="Dexterity";break;case c.ABILITY_CON:h="Constitution";break;case c.ABILITY_INT:h="Intelligence";break;case c.ABILITY_WIS:h="Wisdom";break;case c.ABILITY_CHA:h="Charisma";break}if(d>0){h+=" +"+d}var l='onclick="builder.ui.clickROTExtraAbility(event,'+e+');"';return'<a title="'+h+'" style="font-family:arial,serif;" class="select'+b+'" '+l+">"+(d>0?"+":"")+d+"</a>"};builderOutput.prototype.featSelectors=function(a){var q=builder.constant;var h=builder.rules;var g=builder.summary;var s=builder.build;var b=32;var t=(new dataTable()).table("classes").row(s.level[a].class_id);var j=s.level[a].class_id;var c=builder.classLevel(a,j);var o=(new dataTable()).table(t.field("bonusfeatstable"));var f="";var d,n="none";var m=s.level[a];var r,k,l,e,u;d=o.row(false,c-1).field("bonus",0);if(d){for(var p=0;p<d;p++){k=build.feat.get(q.FEAT_TYPE_SUBSELECT,a,p);r=(k.id==q.ID_NONE)?"":'<span class="icon" style="background-image:url('+builder.directory.icons+"16x16/"+k.icon+'.png)"></span>';l=(k.id==q.ID_NONE)?"":build.feat.validate(k.id,a,p,q.FEAT_TYPE_SUBSELECT).output();e=(k.id==q.ID_NONE)?"Select Bonus Feat (Sub-select)":k.label;if(e.length>b){e=e.substring(0,b)+".."}u=(k.id==q.ID_NONE)?"":'title="feat:'+k.id+'" ';f+="<a "+u+'class="classFeat'+(k.id>=0?"":" empty")+'" data-level="'+a+'" data-slot="'+p+'" data-type="'+q.FEAT_TYPE_SUBSELECT+'" id="bonusfeat_'+a+"_"+p+'" onclick="builder.selector.generic.open('+q.SELECTOR_FEAT+","+a+","+p+","+q.FEAT_TYPE_SUBSELECT+');">'+r+e+l+"</a>"}}d=o.row(false,c-1).field("normal",0);if(d){for(var p=0;p<d;p++){k=build.feat.get(q.FEAT_TYPE_BONUS,a,p);r=(k.id==q.ID_NONE)?"":'<span class="icon" style="background-image:url('+builder.directory.icons+"16x16/"+k.icon+'.png)"></span>';l=(k.id==q.ID_NONE)?"":build.feat.validate(k.id,a,p,q.FEAT_TYPE_BONUS).output();e=(k.id==q.ID_NONE)?"Select Bonus Feat":k.label;if(e.length>b){e=e.substring(0,b)+".."}u=(k.id==q.ID_NONE)?"":'title="feat:'+k.id+'" ';f+="<a "+u+'class="classFeat'+(k.id>=0?"":" empty")+'" data-level="'+a+'" data-slot="'+p+'" data-type="'+q.FEAT_TYPE_BONUS+'" id="bonusfeat_'+a+"_"+p+'" onclick="builder.selector.generic.open('+q.SELECTOR_FEAT+","+a+","+p+","+q.FEAT_TYPE_BONUS+');">'+r+e+l+"</a>"}}if(a==1&&g.feats.have(h.featid_quick_to_master,a)){k=build.feat.get(q.FEAT_TYPE_QUICK_TO_MASTER,1,0);if(k.id===undefined){k.id=q.ID_NONE}r=(k.id==q.ID_NONE)?"":'<span class="icon" style="background-image:url('+builder.directory.icons+"16x16/"+k.icon+'.png)"></span>';l=(k.id==q.ID_NONE)?"":build.feat.validate(k.id,a,p,q.FEAT_TYPE_QUICK_TO_MASTER).output();e=(k.id==q.ID_NONE)?"Select Quick to Master Feat":k.label;if(e.length>b){e=e.substring(0,b)+".."}u=(k.id==q.ID_NONE)?"":'title="feat:'+k.id+'" ';f+="<a "+u+'class="classFeat'+(k.id>=0?"":" empty")+'" data-level="'+a+'" data-slot="0" data-type="'+q.FEAT_TYPE_QUICK_TO_MASTER+'" id="bonusfeat_'+a+'_0" onclick="builder.selector.generic.open('+q.SELECTOR_FEAT+","+a+",0,"+q.FEAT_TYPE_QUICK_TO_MASTER+');">'+r+e+l+"</a>"}if(d=h.feat_gain[a]){for(var p=0;p<d;p++){k=build.feat.get(q.FEAT_TYPE_NORMAL,a,p);r=(k.id==q.ID_NONE)?"":'<span class="icon" style="background-image:url('+builder.directory.icons+"16x16/"+k.icon+'.png)"></span>';l=(k.id==q.ID_NONE)?"":build.feat.validate(k.id,a,p,q.FEAT_TYPE_NORMAL).output();e=(k.id==q.ID_NONE)?"Select Feat":k.label;if(e.length>b){e=e.substring(0,b)+".."}u=(k.id==q.ID_NONE)?"":'title="feat:'+k.id+'" ';f+="<a "+u+'class="classFeat'+(k.id>=0?"":" empty")+'" data-level="'+a+'" data-slot="'+p+'" data-type="'+q.FEAT_TYPE_NORMAL+'" id="feat_'+a+"_"+p+'" onclick="builder.selector.generic.open('+q.SELECTOR_FEAT+","+a+","+p+","+q.FEAT_TYPE_NORMAL+');">'+r+e+l+"</a>"}}return f};builderOutput.prototype.featExtra=function(a,o){var r=builder.constant;var l=builder.rules;var k=builder.summary;var t=builder.build;var m=t.level[a].class_id;var b=builder.classLevel(a,m);var c=(new dataTable()).table("feat");var j="";var g;var d=builder.config.feats_extra_display_type;var n,h,s,p,f;var e=k.feats.fetch(a,r.FEAT_TYPE_AUTO);var g=e.length;for(var q=0;q<g;q++){n=e[q];if(n.id==r.ID_NONE||n.label==r.ID_NONE){continue}if(o.find(n.id)){continue}f=c.row(n.id);h=(n.prefix!==undefined)?n.prefix:"";h+=n.label;s=builder.directory.icons+"30x30/"+f.field("icon")+".png";p="<strong>"+h+"</strong><br>"+f.field("description");if(d==r.CONFIG_DISPLAY_ICON){j+='<div class="feat_icon_extra" title="'+h+'" style="background-image:url('+s+')"></div>'}else{j+='<li title="feat:'+n.id+'">- '+h+"</li>"}o.push(n.id)}if(d==r.CONFIG_DISPLAY_ICON){return j}return(j.length)?'<ul class="extra">'+j+"</ul>":""};builder.output=new builderOutput();builder.tick("Game Rules");var builderRules=function(){};builderRules.prototype.scripts=[];builderRules.prototype.addScript=function(a,b,c){if(this.scripts[a]==undefined){this.scripts[a]=[]}this.scripts[a].push({label:b,execute:c});builder.log("SCRIPT",'Added Game Script "'+b+'"')};builderRules.prototype.runScripts=function(b,e){if(this.scripts==undefined){return e}var a=this.scripts;var c,d=a.length;for(c=0;c<d;c++){e=a[c].execute(e)}return e};builderRules.prototype.featid_able_learner=1774;builderRules.prototype.featid_skilled=1773;builderRules.prototype.featid_quick_to_master=258;builderRules.prototype.featid_mind_over_body=1104;builderRules.prototype.featid_weapon_finesse=42;builderRules.prototype.featid_zen_archery=412;builderRules.prototype.featid_2wf=41;builderRules.prototype.featid_2wf_ranger=1729;builderRules.prototype.featid_shadow_theif=1771;builderRules.prototype.featid_intuitive_attack=3357;builderRules.prototype.max_classes=4;builderRules.prototype.abilities=[{id:"STR",value:8,label:"Strength"},{id:"DEX",value:8,label:"Dexterity"},{id:"CON",value:8,label:"Constitution"},{id:"INT",value:8,label:"Intelligence"},{id:"WIS",value:8,label:"Wisdom"},{id:"CHA",value:8,label:"Charisma"}];builderRules.prototype.ability_selection=[4,8,12,16,20,24,28,32,36,40];builderRules.prototype.ability_points=32;builderRules.prototype.rot_epic_relevel=1;builderRules.prototype.rot_epic_relevel_points=5;builderRules.prototype.saving_throws=[{id:"FORT",value:0,label:"Fortitude"},{id:"REFL",value:0,label:"Reflex"},{id:"WILL",value:0,label:"Will"}];builderRules.prototype.feat_groups=[{label:"Weapon Focus...",category:"general_ft_cat",feats:[123,110,43,291,90,91,125,126,952,1590,114,111,1601,107,112,108,92,116,117,122,118,93,113,101,106,94,95,96,104,105,121,1645,1634,103,102,120,98,99,97,1667,1656,109,127,100,115,1826,993,2107,2108]},{label:"Improved Critical...",category:"general_ft_cat",feats:[85,72,15,292,52,53,87,88,954,1589,76,73,1600,69,74,70,54,78,79,84,80,55,75,63,68,56,57,58,66,67,83,1644,1633,65,64,82,60,61,59,1666,1655,71,89,62,77,1825,995,2109,2110]},{label:"Skill Focus...",category:"skillnsave_ft_cat",feats:[34,404,915,173,1331,911,407,912,185,174,175,177,178,916,179,180,181,182,183,184,187,188,186,189,190,1333,192,406,193]},{label:"Epic Skill Focus...",category:"epic_ft_cat",feats:[588,917,589,1334,913,590,914,591,593,918,596,598,600,604,1336,607,592,601]},{label:"Spell Focus...",category:"spellcasting_ft_cat",feats:[35,166,167,168,169,170,171,172]},{label:"Extra Spell Slot (Bard)...",category:"spellcasting_ft_cat",feats:[1283,1284,1285,1286,1287,1288]},{label:"Extra Spell Slot (Cleric)...",category:"spellcasting_ft_cat",feats:[1289,1290,1291,1292,1293,1294,1295,1296,1297]},{label:"Extra Spell Slot (Druid)...",category:"spellcasting_ft_cat",feats:[1298,1299,1300,1301,1302,1303,1304,1305,1306]},{label:"Extra Spell Slot (Sorcerer)...",category:"spellcasting_ft_cat",feats:[1313,1314,1315,1316,1317,1318,1319,1320,1321]},{label:"Extra Spell Slot (Wizard)...",category:"spellcasting_ft_cat",feats:[1322,1323,1324,1325,1326,1327,1328,1329,1330]},{label:"Extra Spell Slot (Spirit Shaman)...",category:"spellcasting_ft_cat",feats:[2004,2005,2006,2007,2008,2009,2010,2011,2012]},{label:"Extra Spell Slot (Favored Soul)...",category:"spellcasting_ft_cat",feats:[2069,2070,2071,2072,2073,2074,2075,2076,2077]},{label:"Extra Spell Slot (Paladin)...",category:"spellcasting_ft_cat",feats:[1307,1308,1309]},{label:"Extra Spell Slot (Ranger)...",category:"spellcasting_ft_cat",feats:[1310,1311,1312]}];builderRules.prototype.auto_feat_requirements=[{feats:[1731,1732,1733],requires:1730},{feats:[1734,1735,1736],requires:1729}];builderRules.prototype.feat_rename={1731:"Rapid Shot (Ranger)",1732:"Manyshot (Ranger)",1733:"Improved Rapid Shot (Ranger)",1734:"Two-Weapon Fighting (Ranger)",1735:"Improved Two-Weapon Fighting (Ranger)",1736:"Greater Two-Weapon Fighting (Ranger)",1973:"Perfect Two-Weapon Fighting (Ranger)",1975:"One Shot (Ranger)"};builderRules.prototype.max_level=20;builderRules.prototype.max_store_level=40;builderRules.prototype.feat_gain=[];builderRules.prototype.background=[];builderRules.prototype.feat=[];builderRules.prototype.compiled=[];builderRules.prototype.pool=[];builderRules.prototype.initialise=function(){this.compiled=[];for(var a=1;a<=this.max_store_level;a++){this.compiled[a]={normal:[],bonus:[],subselect:[],auto:[]}}};builderRules.prototype.loadSet=function(f,e){var b=builder.constant;switch(f){case b.GAME_VERSION_KAEDRIN:var a="Kaedrin's Class Pack";break;case b.GAME_VERSION_MOW:var a="Mysteries of Westgate";break;case b.GAME_VERSION_SOZ:var a="Storm of Zehir";break;case b.GAME_VERSION_MOTB:var a="Mask of the Betrayer";break;case b.GAME_VERSION_ROTE:var a="Realms of Trinity (Easy)";break;case b.GAME_VERSION_ROTN:var a="Realms of Trinity (Normal)";break;default:var a="Official Campaign";break}var d=(builder.game_version=="rote"||builder.game_version=="rotn")?"rot":builder.game_version;var c=[{file:builder.directory.data+d+"/classes.pack.js",label:"Class Information"},{file:builder.directory.data+d+"/racial.pack.js",label:"Racial Information"},{file:builder.directory.data+d+"/hench.pack.js",label:"Companions and Familiars"},{file:builder.directory.data+d+"/extra.pack.js",label:"Extended Class Information"},{file:builder.directory.data+d+"/feat.js",label:"Feats"},{file:builder.directory.data+d+"/skills.js",label:"Skills"}];c.push({file:builder.directory.rules+f+".js",label:"Rules: "+a});c.push({file:builder.directory.rules+"oc_baseitems.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"oc_feats.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"oc_scripts.js",label:"Rules: "+a});if([b.GAME_VERSION_MOTB,b.GAME_VERSION_SOZ,b.GAME_VERSION_KAEDRIN,b.GAME_VERSION_ROTE,b.GAME_VERSION_ROTN].find(f)){c.push({file:builder.directory.rules+"x1_baseitems.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"x1_feats.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"x1_scripts.js",label:"Rules: "+a})}if([b.GAME_VERSION_SOZ,b.GAME_VERSION_KAEDRIN,b.GAME_VERSION_ROTE,b.GAME_VERSION_ROTN].find(f)){c.push({file:builder.directory.rules+"x2_baseitems.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"x2_feats.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"x2_scripts.js",label:"Rules: "+a})}if([b.GAME_VERSION_KAEDRIN].find(f)){c.push({file:builder.directory.rules+"kaedrin_baseitems.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"kaedrin_feats.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"kaedrin_scripts.js",label:"Rules: "+a})}if([b.GAME_VERSION_ROTE].find(f)){c.push({file:builder.directory.rules+"rote_baseitems.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"rote_feats.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"rote_scripts.js",label:"Rules: "+a})}if([b.GAME_VERSION_ROTN].find(f)){c.push({file:builder.directory.rules+"rotn_baseitems.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"rotn_feats.js",label:"Rules: "+a});c.push({file:builder.directory.rules+"rotn_scripts.js",label:"Rules: "+a})}$(".version2da").remove();builder.load(c,e,"version2da")};builderRules.prototype.compile=function(){var g=builder.constant;var h=builder.summary;builder.log("rules","Compiling");var a=[];this.pool=[];var c,b,l,f,e;var d=this.max_level;while(d>0){this.compiled[d]={normal:[],bonus:[],subselect:[],auto:[]};e=h.feats.fetch(d,g.FEAT_TYPE_ANY);c=e.length;while(c--){f=e[c].id;if(this.feat[f]===undefined){continue}l=this.feat[f];l.id=f;l.label=e[c].label;this.pool.push(l);switch(e[c].type){case g.FEAT_TYPE_NORMAL:this.compiled[d].normal.push(l);break;case g.FEAT_TYPE_QUICK_TO_MASTER:case g.FEAT_TYPE_BONUS:this.compiled[d].bonus.push(l);break;case g.FEAT_TYPE_SUBSELECT:this.compiled[d].subselect.push(l);break;default:this.compiled[d].auto.push(l);break}}d--}return true};builderRules.prototype.affect=function(z,g,t,a,G){var H=builder.constant;var w=builder.summary;var I=builder.build;if(G===undefined){G=H.FEAT_TYPE_ANY}var E=this.max_level;var r,q;var F,D,C,B,o,J,x,c,u,K,e,s;var n=t.length;for(F=0;F<n;F++){o=t[F];if(o.script!==undefined){var u=o.script(a,G);if(u===false){continue}u.id=o.id;u.label=o.label;o=u}r=false;if((g&H.AFFECT_SNEAK_ATTACK)&&o.sneak_attack!==undefined){z.value+=o.sneak_attack[0];if(o.sneak_attack[2]==undefined){z.value_prestige+=o.sneak_attack[0]}z.effects.push([o.label,o.sneak_attack[0]])}if((g&H.AFFECT_SKILLS)&&o.skill!==undefined){B=o.skill.length;while(B--){D=z.length;while(D--){if(z[D].id==o.skill.type){if(o.skill.class_level!==undefined){q=w.classes.fetch(a);c=0;C=o.skill.class_level.length;while(C--){if(q.classes[o.skill[B].class_level[C]]!==undefined){if(q.classes[o.skill[B].class_level[C]].levels>c){c=q.classes[o.skill[B].class_level[C]].levels}}}if(c>0){z[D].value+=c;z[D].effects.push([o.label,c])}}if(o.skill.progression!==undefined){K=this.progression(o.skill[B].progression,a);z[D].value+=K;z[D].effects.push([o.label,K])}if(o.skill[B].value!==undefined){z[D].value+=o.skill[B].value;z[D].effects.push([o.label,o.skill[B].value])}}}}}if((g&H.AFFECT_CASTER_LEVEL)&&o.caster!==undefined){s=0;var f=(o.caster.use_feat_label!==undefined)?o.label:"Practiced Spellcaster";if(o.caster.levels!==undefined){s=o.caster.levels}if(o.caster.progression!==undefined){s+=this.progression(o.caster.progression,a)}if(z.arcane.classes[o.caster.class_id]!==undefined){if(z.arcane.classes[o.caster.class_id].multiclassed!=1&&z.arcane.classes[o.caster.class_id].level>=E){continue}z.arcane.classes[o.caster.class_id].value+=s;z.arcane.classes[o.caster.class_id].effects.push([f,s]);if(z.arcane.index==o.caster.class_id){z.arcane.high+=s}else{if(z.arcane.high<z.arcane.classes[o.caster.class_id].value){z.arcane.high=z.arcane.classes[o.caster.class_id].value;z.arcane.index=o.caster.class_id}}}if(z.divine.classes[o.caster.class_id]!==undefined){if(z.divine.classes[o.caster.class_id].multiclassed!=1&&z.divine.classes[o.caster.class_id].level>=E){continue}z.divine.classes[o.caster.class_id].value+=s;z.divine.classes[o.caster.class_id].effects.push([f,s]);if(z.divine.index==o.caster.class_id){z.divine.high+=s}else{if(z.divine.high<z.divine.classes[o.caster.class_id].value){z.divine.high=z.divine.classes[o.caster.class_id].value;z.divine.index=o.caster.class_id}}}if(z.invoke.classes[o.caster.class_id]!==undefined){if(z.invoke.classes[o.caster.class_id].multiclassed!=1&&z.invoke.classes[o.caster.class_id].level>=E){continue}z.invoke.classes[o.caster.class_id].value+=s;z.invoke.classes[o.caster.class_id].effects.push([f,s]);if(z.invoke.index==o.caster.class_id){z.invoke.high+=s}else{if(z.invoke.high<z.invoke.classes[o.caster.class_id].value){z.invoke.high=z.invoke.classes[o.caster.class_id].value;z.invoke.index=o.caster.class_id}}}}if((g&H.AFFECT_SPELL_DC)&&o.spell_dc!==undefined){D=o.spell_dc.length;while(D--){if(o.spell_dc[D].school==H.SCHOOL_SPECIALISATION){if(I.school.id!=H.ID_NONE&&I.school.id!=H.SCHOOL_GENERAL){z[I.school.id].value+=o.spell_dc[D].value;z[I.school.id].effects.push([o.label,o.spell_dc[D].value])}}else{C=10;while(C--){if(o.spell_dc[D].school==C||o.spell_dc[D].school==H.SCHOOL_ALL){z[C].value+=o.spell_dc[D].value;z[C].effects.push([o.label,o.spell_dc[D].value])}}}}}if((g&H.AFFECT_SPELL_DC_BASE)&&o.spell_dc_base!==undefined){z.base+=o.spell_dc_base.value;z.effects.push([o.label,o.spell_dc_base.value])}if((g&H.AFFECT_ATTACK)){if(o.weapon!==undefined){if(o.weapon.attack!==undefined){var A=o.weapon.applies;var d=false;var b=false;var p=false;var h=false;var y;D=A.length;while(D--){y=(A[D]===H.WEAPON_OF_CHOICE)?this.findSuperiorWeaponFocusBaseItem(a):A[D];if(d==false&&builder.constant.WEAPON_TYPES_MELEE.find(y)){d=true;z.melee.main_hand.value+=o.weapon.attack;z.melee.main_hand.effects.push([o.label,o.weapon.attack]);z.melee.dual_main.value+=o.weapon.attack;z.melee.dual_main.effects.push([o.label,o.weapon.attack]);z.melee.dual_off.value+=o.weapon.attack;z.melee.dual_off.effects.push([o.label,o.weapon.attack])}if(b==false&&builder.constant.WEAPON_TYPES_MELEE_TOUCH.find(y)){b=true;z.melee.touch.value+=o.weapon.attack;z.melee.touch.effects.push([o.label,o.weapon.attack])}if(p==false&&builder.constant.WEAPON_TYPES_RANGED.find(y)){p=true;z.ranged.main_hand.value+=o.weapon.attack;z.ranged.main_hand.effects.push([o.label,o.weapon.attack])}if(h==false&&builder.constant.WEAPON_TYPES_RANGED_TOUCH.find(y)){h=true;z.ranged.touch.value+=o.weapon.attack;z.ranged.touch.effects.push([o.label,o.weapon.attack])}}}}if(o.attack!==undefined){z.melee.main_hand.value+=o.attack;z.melee.main_hand.effects.push([o.label,o.attack]);z.melee.dual_main.value+=o.attack;z.melee.dual_main.effects.push([o.label,o.attack]);z.melee.dual_off.value+=o.attack;z.melee.dual_off.effects.push([o.label,o.attack]);z.melee.touch.value+=o.attack;z.melee.touch.effects.push([o.label,o.attack]);z.ranged.main_hand.value+=o.attack;z.ranged.main_hand.effects.push([o.label,o.attack]);z.ranged.touch.value+=o.attack;z.ranged.touch.effects.push([o.label,o.attack])}if(o.attack_gain!==undefined){D=o.attack_gain.length;while(D--){s=o.attack_gain[D].value;e=(o.attack_gain[D].penalty!==undefined)?o.attack_gain[D].penalty:0;switch(o.attack_gain[D].apply){case H.WEAPON_HAND_MAIN:z.melee.main_hand.gain.push(e);break;case H.WEAPON_HAND_OFF:z.melee.dual_off.gain.push(e);break;case H.WEAPON_HAND_RANGED:z.melee.ranged.gain.push(e);break}}}if(o.attack_mod!==undefined){D=o.attack_mod.length;while(D--){s=o.attack_mod[D].value;if(o.attack_mod[D].progression!==undefined){s=this.progression(o.attack_mod[D].progression,a)}switch(o.attack_mod[D].apply){case H.WEAPON_HAND_ANY:z.melee.main_hand.value+=s;z.melee.main_hand.effects.push([o.label,s]);z.melee.dual_main.value+=s;z.melee.dual_main.effects.push([o.label,s]);z.melee.dual_off.value+=s;z.melee.dual_off.effects.push([o.label,s]);z.ranged.main_hand.value+=s;z.ranged.main_hand.effects.push([o.label,s]);z.melee.touch.value+=s;z.melee.touch.effects.push([o.label,s]);z.ranged.touch.value+=s;z.ranged.touch.effects.push([o.label,s]);break;case H.WEAPON_HAND_TOUCH_MELEE:z.melee.touch.value+=s;z.melee.touch.effects.push([o.label,s]);break;case H.WEAPON_HAND_TOUCH_RANGED:z.ranged.touch.value+=s;z.ranged.touch.effects.push([o.label,s]);break;case H.WEAPON_HAND_DUAL:z.melee.main_hand.value+=s;z.melee.main_hand.effects.push([o.label,s]);z.melee.dual_main.value+=s;z.melee.dual_main.effects.push([o.label,s]);z.melee.dual_off.value+=s;z.melee.dual_off.effects.push([o.label,s]);break;case H.WEAPON_HAND_MAIN:z.melee.main_hand.value+=s;z.melee.main_hand.effects.push([o.label,s]);z.melee.dual_main.value+=s;z.melee.dual_main.effects.push([o.label,s]);break;case H.WEAPON_HAND_OFF:z.melee.dual_off.value+=s;z.melee.dual_off.effects.push([o.label,s]);break;case H.WEAPON_HAND_RANGED:z.ranged.main_hand.value+=s;z.ranged.main_hand.effects.push([o.label,s]);break}}}}if((g&H.AFFECT_ARMOR)&&o.armor!==undefined){D=o.armor.length;while(D--){K=0;if(o.armor[D].progression!==undefined){K+=this.progression(o.armor[D].progression,a)}if(o.armor[D].value!==undefined){K+=o.armor[D].value}if(o.armor[D].lowest!==undefined){if(!r){r=w.abilities.fetch(a,G)}K+=this.findValue(o.armor,false,r,a)}if(o.armor[D].highest!==undefined){if(!r){r=w.abilities.fetch(a,G)}K+=this.findValue(o.armor,true,r,a)}if(o.armor[D].ability!==undefined){if(!r){r=w.abilities.fetch(a,G)}c=r[o.armor[D].ability].modifier;if(c>0){K+=c}}if(K!=0){z[o.armor[D].type].value+=K;z[o.armor[D].type].effects.push([o.label,K])}}}if((g&H.AFFECT_RESISTANCE)&&o.resist!==undefined){D=o.resist.length;while(D--){if(o.resist[D].type_by_feat!==undefined){o.resist[D].type=false;var v=o.resist[D].type_by_feat;C=v.length;while(C--){B=v[C].feat.length;while(B--){if(w.feats.have(v[C].feat[B],a)){o.resist[D].type=v[C].type;break}}if(o.resist[D].type!==false){break}}if(o.resist[D].type===false){continue}}if(z[o.resist[D].type]===undefined){z[o.resist[D].type]={value:0,label:"",effects:[]}}switch(o.resist[D].type){case H.RESIST_TYPE_FEAR:z[o.resist[D].type].label="Fear";break;case H.RESIST_TYPE_CRITICAL:z[o.resist[D].type].label="Critical Hits";break;case H.RESIST_TYPE_POISON:z[o.resist[D].type].label="Poison";break;case H.RESIST_TYPE_DISEASE:z[o.resist[D].type].label="Disease";break;case H.RESIST_TYPE_ACID:z[o.resist[D].type].label="Acid";break;case H.RESIST_TYPE_COLD:z[o.resist[D].type].label="Cold";break;case H.RESIST_TYPE_ELECTRICAL:z[o.resist[D].type].label="Electrical";break;case H.RESIST_TYPE_FIRE:z[o.resist[D].type].label="Fire";break;case H.RESIST_TYPE_SONIC:z[o.resist[D].type].label="Sonic";break;case H.RESIST_TYPE_PARALYSIS:z[o.resist[D].type].label="Paralysis";break;case H.RESIST_TYPE_SPELL:z[o.resist[D].type].label="Spell";break;case H.RESIST_TYPE_MIND:z[o.resist[D].type].label="Mind";break;case H.RESIST_TYPE_STUN:z[o.resist[D].type].label="Stun";break;case H.RESIST_TYPE_HOLD:z[o.resist[D].type].label="Hold";break;case H.RESIST_TYPE_SLEEP:z[o.resist[D].type].label="Sleep";break;case H.RESIST_TYPE_DEATH:z[o.resist[D].type].label="Death";break;case H.RESIST_TYPE_ABILITY_DRAIN:z[o.resist[D].type].label="Ability Drain";break;case H.RESIST_TYPE_ENERGY_DRAIN:z[o.resist[D].type].label="Energy Drain";break;case H.RESIST_TYPE_CHARM:z[o.resist[D].type].label="Charm";break;case H.RESIST_TYPE_DOMINATE:z[o.resist[D].type].label="Dominate";break;case H.RESIST_TYPE_CRITICAL:z[o.resist[D].type].label="Critical Hits";break;case H.RESIST_TYPE_SNEAK:z[o.resist[D].type].label="Sneak Attacks";break;default:z[o.resist[D].type].label="Unknown";break}c=0;if(o.resist[D].per_level!==undefined){c+=(E*o.resist[D].per_level)}if(o.resist[D].class_level!==undefined){c+=w.classes.level([o.resist[D].class_level],a)}if(o.resist[D].value!==undefined){c+=o.resist[D].value}if(o.resist[D].feats!==undefined){var C=o.resist[D].feats.length;while(C--){if(w.feats.have(o.resist[D].feats[C],a)){c+=o.resist[D].multiplier}}}if(o.resist[D].progression!==undefined){c+=this.progression(o.resist[D].progression,a)}if(c!=0){if(o.resist[D].type==H.RESIST_TYPE_SPELL){var m=(o.resist[D].stack===undefined)?false:true;if(!m&&z[o.resist[D].type].value>c){}else{z[o.resist[D].type].value+=c;z[o.resist[D].type].effects.push([o.label,c])}}else{if(c==H.RESIST_IMMUNE||z[o.resist[D].type].value==H.RESIST_IMMUNE){z[o.resist[D].type].value=H.RESIST_IMMUNE}else{z[o.resist[D].type].value+=c}z[o.resist[D].type].effects.push([o.label,c])}}}}if((g&H.AFFECT_REDUCTION)&&o.damage_reduction!==undefined){if(z[o.damage_reduction.overcome]===undefined){z[o.damage_reduction.overcome]={value:0,label:"",effects:[]}}switch(o.damage_reduction.overcome){case H.REDUCTION_COLD_IRON:z[o.damage_reduction.overcome].label="cold iron";break;case H.REDUCTION_SILVER:z[o.damage_reduction.overcome].label="silver";break;case H.REDUCTION_MAGIC:z[o.damage_reduction.overcome].label="magic";break;case H.REDUCTION_PHYSICAL:z[o.damage_reduction.overcome].label="physical";break;case H.REDUCTION_NONE:z[o.damage_reduction.overcome].label="-";break}var c=0;if(o.damage_reduction.value!==undefined){c+=o.damage_reduction.value}if(o.feats!==undefined){D=o.feats.length;while(D--){if(w.feat.have(o.feats[D],a)){c++}}}if(o.damage_reduction.progression!==undefined){c+=this.progression(o.damage_reduction.progression,a)}z[o.damage_reduction.overcome].value+=c;z[o.damage_reduction.overcome].effects.push([o.label,c])}if((g&H.AFFECT_HP)){if(o.hp!==undefined){z.value+=o.hp;z.effects.push([o.label,o.hp])}if(o.hp_per_level!==undefined){z.value+=(o.hp_per_level*a);z.effects.push([o.label,(o.hp_per_level*a)])}}if((g&H.AFFECT_STR)&&o.strength!==undefined){if(o.strength.progression!==undefined){if(u=this.progression(o.strength.progression,a)){z.value+=u;z.effects.push([o.label,u])}}else{z.value+=o.strength.value;z.effects.push([o.label,o.strength.value])}}if((g&H.AFFECT_DEX)&&o.dexterity!==undefined){if(o.dexterity.progression!==undefined){if(u=this.progression(o.dexterity.progression,a)){z.value+=u;z.effects.push([o.label,u])}}else{z.value+=o.dexterity.value;z.effects.push([o.label,o.dexterity.value])}}if((g&H.AFFECT_CON)&&o.constitution!==undefined){if(o.constitution.progression!==undefined){if(u=this.progression(o.constitution.progression,a)){z.value+=u;z.effects.push([o.label,u])}}else{z.value+=o.constitution.value;z.effects.push([o.label,o.constitution.value])}}if((g&H.AFFECT_INT)&&o.intelligence!==undefined){if(o.intelligence.progression!==undefined){if(u=this.progression(o.intelligence.progression,a)){z.value+=u;z.effects.push([o.label,u])}}else{z.value+=o.intelligence.value;z.effects.push([o.label,o.intelligence.value])}}if((g&H.AFFECT_WIS)&&o.wisdom!==undefined){if(o.wisdom.progression!==undefined){if(u=this.progression(o.wisdom.progression,a)){z.value+=u;z.effects.push([o.label,u])}}else{z.value+=o.wisdom.value;z.effects.push([o.label,o.wisdom.value])}}if((g&H.AFFECT_CHA)&&o.charisma!==undefined){if(o.charisma.progression!==undefined){if(u=this.progression(o.charisma.progression,a)){z.value+=u;z.effects.push([o.label,u])}}else{z.value+=o.charisma.value;z.effects.push([o.label,o.charisma.value])}}if((g&H.AFFECT_SAVING_THROWS)&&o.save!==undefined){J=o.save;D=J.length;while(D--){if(J[D].progression!==undefined){if(u=this.progression(J[D].progression,a)){z[J[D].type].value+=u;z[J[D].type].effects.push([o.label,u])}}else{if(o.save[D].lowest!==undefined){if(!r){r=w.abilities.fetch(a,G)}K=this.findValue(o.save,false,r,a);z[J[D].type].value+=K;z[J[D].type].effects.push([o.label,K])}if(o.save[D].highest!==undefined){if(!r){r=w.abilities.fetch(a,G)}K=this.findValue(o.save,true,r,a);z[J[D].type].value+=K;z[J[D].type].effects.push([o.label,K])}if(J[D].value!==undefined){z[J[D].type].value+=J[D].value;z[J[D].type].effects.push([o.label,J[D].value])}if(J[D].ability!==undefined){if(!r){r=w.abilities.fetch(a,G)}c=r[J[D].ability].modifier;if(c>0){z[J[D].type].value+=c;z[J[D].type].effects.push([o.label,c])}}}}}}return z};builderRules.prototype.progression=function(f,a){var k=builder.summary;var b=f.classes;if(f.if_feat!==undefined){if(k.feats.have(f.if_feat.id,a)){b=b.concat(f.if_feat.classes)}}var d=k.classes.level(b,a);if(f.start!==undefined){var g=0;var c=(f.gain!==undefined)?f.gain:1;var h=(f.max!==undefined)?f.max:this.max_level;for(var e=f.start;e<=d;e=e+c){if(e>h){break}g+=f.value}return g}else{var l=f.levels;var e=l.length;while(e--){if(d>=l[e]){return f.values[e]}}}return 0};builderRules.prototype.findValue=function(g,b,e,a){var f=builder.constant;var h=builder.summary;if(b===undefined){b=false}var k=false;if(b==true&&g.highest!==undefined){k=g.highest}if(b==false&&g.lowest!==undefined){k=g.lowest}if(k==false){return 0}var d=k.length;var l=[];var c;while(d--){switch(k[d].type){case f.CONDITION_ABILITY:c=e[k[d].value].modifier;if(c<0){c=0}if(k[d].minimum!==undefined){if(c<k[d].minimum){c=k[d].minimum}}l.push(c);break;case f.CONDITION_CLASS_LEVEL:c=h.classes.level([k[d].value],a);if(c<0){c=0}if(k[d].minimum!==undefined){if(c<k[d].minimum){c=k[d].minimum}}l.push(c);break}}if(l.length>0){return(b==true)?l.high():l.low()}return 0};builderRules.prototype.findSuperiorWeaponFocusBaseItem=function(c){var a=builder.constant;var b=builder.summary;switch(true){case b.feats.have(879,c):return a.BASE_ITEM_SICKLE;case b.feats.have(880,c):return a.BASE_ITEM_KAMA;case b.feats.have(881,c):return a.BASE_ITEM_KUKRI;case b.feats.have(919,c):return a.BASE_ITEM_CLUB;case b.feats.have(920,c):return a.BASE_ITEM_DAGGER;case b.feats.have(921,c):return a.BASE_ITEM_MACE;case b.feats.have(922,c):return a.BASE_ITEM_MORNINGSTAR;case b.feats.have(923,c):return a.BASE_ITEM_QUARTERSTAFF;case b.feats.have(924,c):return a.BASE_ITEM_SPEAR;case b.feats.have(925,c):return a.BASE_ITEM_SHORTSWORD;case b.feats.have(926,c):return a.BASE_ITEM_RAPIER;case b.feats.have(927,c):return a.BASE_ITEM_SCIMITAR;case b.feats.have(928,c):return a.BASE_ITEM_LONGSWORD;case b.feats.have(929,c):return a.BASE_ITEM_GREATSWORD;case b.feats.have(930,c):return a.BASE_ITEM_HANDAXE;case b.feats.have(931,c):return a.BASE_ITEM_BATTLEAXE;case b.feats.have(932,c):return a.BASE_ITEM_GREATAXE;case b.feats.have(933,c):return a.BASE_ITEM_HALBERD;case b.feats.have(934,c):return a.BASE_ITEM_LIGHTHAMMER;case b.feats.have(935,c):return a.BASE_ITEM_LIGHTFLAIL;case b.feats.have(936,c):return a.BASE_ITEM_WARHAMMER;case b.feats.have(938,c):return a.BASE_ITEM_SCYTHE;case b.feats.have(939,c):return a.BASE_ITEM_KATANA;case b.feats.have(940,c):return a.BASE_ITEM_BASTARDSWORD;case b.feats.have(959,c):return a.BASE_ITEM_DWARVENWARAXE;case b.feats.have(1596,c):return a.BASE_ITEM_FALCHION;case b.feats.have(1828,c):return a.BASE_ITEM_WARMACE;default:return a.BASE_ITEM_UNARMED}};builder.rules=new builderRules();builder.tick("Build Outline");var builderBuild=function(){var b=false;var a=false;var c=false};(function(){var a=builder.constant;builder.build={id:a.ID_NONE,name:"",description:"",pros:"",cons:"",notes:"",tags:[],tags_custom:"",race:{id:a.ID_NONE,feats:[],label:"",icon:"blank",base_id:a.ID_NONE,ecl:0,favored:a.ID_NONE,ability:[0,0,0,0,0,0]},background:{id:a.ID_NONE,label:false,feats:[]},deity:{id:a.ID_NONE,label:false},alignment:{id:a.ID_NONE,label:false},ability:{id:[8,8,8,8,8,8],ROT:{1:[0,0,0,0,0,0],2:[0,0,0,0,0,0],3:[0,0,0,0,0,0],4:[0,0,0,0,0,0]},ROTE:[0,0,0,0,0,0]},domain:[{id:a.ID_NONE,label:false,feat:false},{id:a.ID_NONE,label:false,feat:false}],school:{id:a.ID_NONE,label:false},familiar:[],animal:[],level:[],skills:[],spells:[],attacks:{main_hand:[],off_hand:[],ranged:[]},feats:{auto:{},normal:{},bonus:{},subselect:{},qtm:{},rcs:{}}};builderBuild.prototype.saves=[];builderBuild.prototype.scope=builder.constant.SCOPE_BUILD;builderBuild.prototype.importing=false;builderBuild.prototype.initialise=function(c){var j=builder.constant;var l=builder.rules;var g,f=0;var d=(new dataTable()).table("classes").row(f);var m=builder.rules.max_level;var e=builder.rules.max_store_level;if(c===undefined){c=false}for(g=1;g<=e;g++){builder.build.level[g]={class_id:j.ID_NONE,class_icon:"blank",class_label:"",class_level:0,class_skill:0,class_hit_die:0,class_ability_spell:j.ABILITY_INT,class_spellcaster:0,prestige:false,table_feats:false,ability:j.ABILITY_STR,save:{fortitude:0,reflex:0,will:0},caster:{arcane:0,divine:0,invoke:0,progress:j.ID_NONE},spell:{arcane:0,divine:0,invoke:0},bab:0};builder.build.feats.normal[g]={}}this.importing=true;this.ability.value=[];var k=l.abilities;var h=k.length;for(g=0;g<h;g++){this.ability.value.push(k[g].value)}this.saves.value=[];var b=l.saving_throws;for(g in b){this.saves.value.push(b[g].value)}this.race.change(17);this.alignment.change(4);this.deity.change(0);this.classes.level=1;this.classes.change(0,e);this.background.change(0);builder.build.domain=[{id:j.ID_NONE,label:false,feat:false},{id:j.ID_NONE,label:false,feat:false}];builder.build.school={id:j.ID_NONE,label:false};builder.build.familiar=[];builder.build.animal=[];builder.build.skills=[];this.importing=false;l.initialise();if(c==true){return true}this.changed();builder.output.update();return true};builderBuild.prototype.changed=function(e){var c=builder.constant;var d=builder.summary;if(this.importing==true){return true}if(build.hasChanged==false){$(".button.save").removeClass("disabled").find(".hover").html("<strong>Save Changes</strong> made to the build")}build.hasChanged=true;if(e===undefined||e<1){e=1}if(builder.debug){_START_DATE=new Date()}builder.log("build","Changed ("+e+")");var b=build.scope;if(this.forceChange==true){build.scope=c.SCOPE_BUILD}if(build.scope==c.SCOPE_BUILD){build.feat.compileAutoFeats(1);d.cache(e)}switch(this.scope){case c.SCOPE_BUILD:build.classes.calculateCasterLevels();d.caster.cache(e);build.classes.calculateSpellLevels();d.spell.cache(e);build.classes.calculateBAB();d.bab.cache(e);case c.SCOPE_SKILLS:d.skills.cache(e);break;case c.SCOPE_SPELLS:break}build.skills.update(e);if(build.forceChange==true){build.scope=b;build.forceChange=false}if(builder.debug){_END_DATE=new Date();builder.log("update","Processed build in "+((_END_DATE.getTime()-_START_DATE.getTime())/1000)+"ms")}if(!builder.output.pause){builder.output.update(e)}return true};builderBuild.prototype.bab=function(b){var h=builder.build;var d={};var e=0;var c=0;var g;var k=(new dataTable()).table("classes");var f=b;while(f-->1){e=h.level[f].class_id;if(d[e]){continue}c=builder.classLevel(f,e);g=(new dataTable()).table(k.row(e).field("attackbonustable"));d[e]=g.row(c-1).field("bab",0)}var j=0;for(f in d){j+=d[f]}return j}})();var build=new builderBuild();builder.tick("Undo History");builderHistory=function(){};builderHistory.prototype.store=[];builderHistory.prototype.index=0;builderHistory.prototype.ignore=false;builderHistory.prototype.initialise=function(){this.updateLabel()};builderHistory.prototype.add=function(n,e){var g=builder.constant;var l=builder.rules;var j=builder.build;if(this.ignore){return}var k={scope:n,label:"Unknown Entry",data:[g.ID_NONE,g.ID_NONE]};var c;switch(n){case g.HISTORY_SCOPE_RACE:k.label="Race Change";k.data=[j.race.id,e];break;case g.HISTORY_SCOPE_BACKGROUND:k.label="Background Change";k.data=[j.background.id,e];break;case g.HISTORY_SCOPE_DEITY:k.label="Deity Change";k.data=[j.deity.id,e];break;case g.HISTORY_SCOPE_ALIGNMENT:k.label="Alignment Change";k.data=[j.alignment.id,e];break;case g.HISTORY_SCOPE_ABILITY:k.label="Ability Score";k.data={level:e.level,id:[j.level[e.level].ability,e.id]};break;case g.HISTORY_SCOPE_DOMAIN:k.label="Cleric Domain Change";k.data={slot:e.slot,id:[j.domain[e.slot].id,e.id]};break;case g.HISTORY_SCOPE_SCHOOL:k.label="Spell School Change";k.data={slot:e.slot,id:[j.school.id,e.id]};break;case g.HISTORY_SCOPE_FEAT:var b=build.feat.get(e.type,e.level,e.slot).id;switch(e.type){case g.FEAT_TYPE_NORMAL:k.label="Normal Feat Change";break;case g.FEAT_TYPE_SUBSELECT:k.label="Sub-select Feat Change";break;case g.FEAT_TYPE_BONUS:k.label="Bonus Feat Change";break;case g.FEAT_TYPE_QUICK_TO_MASTER:k.label="Quick to Master Feat Change";break;case g.FEAT_TYPE_COMBAT_STYLE:k.label="Ranger Combat Style Change";break}k.data={level:e.level,type:e.type,slot:e.slot,id:[b,e.id]};break;case g.HISTORY_SCOPE_CLASS:k.label="Class Change";k.data={level:e.level,count:e.count,id:[j.level[e.level].class_id,e.id]};break;case g.HISTORY_SCOPE_CLASS_BATCH:var f=[];var m=l.max_level;for(var d=1;d<=m;d++){f[d]=j.level[d].class_id}k.label="Class Change";k.data={old_ids:build.classes.history,new_ids:f};break;case g.HISTORY_SCOPE_FAMILIAR:c=j.level[e.level].class_id;var h=(j.familiar[c]===undefined)?g.ID_NONE:j.familiar[c].id;k.label="Familiar Change";k.data={level:e.level,id:[h,e.id]};break;case g.HISTORY_SCOPE_ANIMAL:c=j.level[e.level].class_id;var a=(j.animal[c]===undefined)?g.ID_NONE:j.animal[c].id;k.label="Animal Companion Change";k.data={level:e.level,id:[a,e.id]};break}if(this.index<this.store.length){this.store.splice(this.index)}this.store.push(k);this.index=this.store.length;this.updateLabel()};builderHistory.prototype._revert=function(b,d){var g=builder.constant;var a=builder.rules;this.ignore=true;var e=(d===undefined)?0:1;var h=b.data;switch(b.scope){case g.HISTORY_SCOPE_RACE:build.race.change(h[e]);build.changed();break;case g.HISTORY_SCOPE_BACKGROUND:build.background.change(h[e]);build.changed();break;case g.HISTORY_SCOPE_DEITY:build.deity.change(h[e]);build.changed();break;case g.HISTORY_SCOPE_ALIGNMENT:build.alignment.change(h[e]);build.changed();break;case g.HISTORY_SCOPE_ABILITY:build.ability.change(h.level,h.id[e]);build.changed();break;case g.HISTORY_SCOPE_DOMAIN:build.domain.change(h.id[e],h.slot);build.changed();break;case g.HISTORY_SCOPE_SCHOOL:build.school.change(h.id[e]);build.changed();break;case g.HISTORY_SCOPE_FEAT:build.feat.level=h.level;build.feat.type=h.type;build.feat.slot=h.slot;build.feat.change(h.id[e]);build.changed();break;case g.HISTORY_SCOPE_CLASS:build.classes.level=h.level;build.classes.change(h.id[e],h.count);build.changed();break;case g.HISTORY_SCOPE_CLASS_BATCH:var c=a.max_level;for(var f=1;f<=c;f++){build.classes.level=f;build.classes.change((e==0)?h.old_ids[f]:h.new_ids[f],1,true)}build.changed();break;case g.HISTORY_SCOPE_FAMILIAR:build.familiar.level=h.level;build.familiar.change(h.id[e]);build.changed();break;case g.HISTORY_SCOPE_ANIMAL:build.animal.level=h.level;build.animal.change(h.id[e]);build.changed();break}this.ignore=false};builderHistory.prototype.updateLabel=function(){if(this.index>=this.store.length){$("#output_utilities .button.redo").addClass("disabled");$("#output_utilities .button.redo .hover").html("Nothing to Redo")}else{$("#output_utilities .button.redo").removeClass("disabled");$("#output_utilities .button.redo .hover").html("Redo "+this.store[this.index].label)}if(this.index<=0){$("#output_utilities .button.undo").addClass("disabled");$("#output_utilities .button.undo .hover").html("Nothing to Undo")}else{$("#output_utilities .button.undo").removeClass("disabled");$("#output_utilities .button.undo .hover").html("Undo "+this.store[this.index-1].label)}};builderHistory.prototype.undo=function(){if(this.store[this.index-1]===undefined){return}this._revert(this.store[this.index-1]);this.index--;this.updateLabel()};builderHistory.prototype.redo=function(){if(this.store[this.index]===undefined){return}this._revert(this.store[this.index],true);this.index++;this.updateLabel()};builder.history=new builderHistory();builder.tick("Build Events");var builderEvents=function(){};builderEvents.prototype.load=function(e){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.log("EVENT","Loading Build #"+e);$(window).scrollTop(0);$("#builder_processing").html("Loading Build...").show();$.ajax({type:"POST",dataType:"json",data:{event:"load_build",id:e},beforeSend:function(){$("body").css("cursor","wait")},complete:function(){$("body").css("cursor","");$("#builder_processing").hide()},error:function(h,g,f){sliph.message("AJAX Tanty!","Failed to load build!")},success:function(o){if(o===undefined||o.build==null||o.id==null){if(o.error!==undefined){sliph.message(o.error[0],o.error[1])}else{sliph.message("Oh Noes!","Failed to load build")}return false}builder.max_level=o.level;builder.rules.max_level=o.level;build.initialise(true);var l,g,f,n,p;var m=o.build;c.id=e;c.name=m.name;c.description=m.description;c.pros=m.pros;c.cons=m.cons;c.notes=m.notes;c.tags=m.tags;c.tags_custom="";builder.output.pause=true;c.ability.id[b.ABILITY_STR]=m.ability.id[b.ABILITY_STR];c.ability.id[b.ABILITY_DEX]=m.ability.id[b.ABILITY_DEX];c.ability.id[b.ABILITY_CON]=m.ability.id[b.ABILITY_CON];c.ability.id[b.ABILITY_INT]=m.ability.id[b.ABILITY_INT];c.ability.id[b.ABILITY_WIS]=m.ability.id[b.ABILITY_WIS];c.ability.id[b.ABILITY_CHA]=m.ability.id[b.ABILITY_CHA];if(builder.game_version=="rote"){c.ability.ROTE=m.ability.ROTE||[0,0,0,0,0,0]}if(builder.game_version=="rote"||builder.game_version=="rotn"){if(m.ability.ROT===undefined){m.ability.ROT={}}c.ability.ROT={1:(m.ability.ROT[1]||[]),2:(m.ability.ROT[2]||[]),3:(m.ability.ROT[3]||[]),4:(m.ability.ROT[4]||[])}}builder.selector.abilities.points=0;build.alignment.change(m.alignment.id,1);build.background.change(m.background.id,1);build.deity.change(m.deity.id,1);if(m.race.id==49){m.race.id=67}if(m.race.id==50){m.race.id=68}build.race.change(m.race.id,1);n=m.level.length;for(l=1;l<n;l++){build.classes.level=l;build.classes.change(m.level[l].class_id,1,1);build.ability.change(l,m.level[l].ability,1)}build.classes.calculateSaves();if(m.feats.normal!==undefined){build.feat.type=b.FEAT_TYPE_NORMAL;for(l in m.feats.normal){build.feat.level=l;for(g in m.feats.normal[l]){if(m.feats.normal[l][g].id===undefined){continue}build.feat.slot=g;build.feat.change(m.feats.normal[l][g].id,1)}}}if(m.feats.bonus!==undefined){build.feat.type=b.FEAT_TYPE_BONUS;for(l in m.feats.bonus){for(g in m.feats.bonus[l]){for(f in m.feats.bonus[l][g]){if(m.feats.bonus[l][g][f].id===undefined){continue}p=build.classes.findLevelByClassLevel(l,g);if(p==false){continue}build.feat.level=p;build.feat.slot=f;build.feat.change(m.feats.bonus[l][g][f].id,1)}}}}if(m.feats.subselect!==undefined){build.feat.type=b.FEAT_TYPE_SUBSELECT;for(l in m.feats.subselect){for(g in m.feats.subselect[l]){for(f in m.feats.subselect[l][g]){if(m.feats.subselect[l][g][f].id===undefined){continue}p=build.classes.findLevelByClassLevel(l,g);if(p==false){continue}build.feat.level=p;build.feat.slot=f;build.feat.change(m.feats.subselect[l][g][f].id,1)}}}}if(m.feats.qtm!==undefined){build.feat.type=b.FEAT_TYPE_QUICK_TO_MASTER;build.feat.level=1;build.feat.slot=0;build.feat.change(m.feats.qtm.id,1)}if(m.feats.rcs!==undefined){build.feat.type=b.FEAT_TYPE_COMBAT_STYLE;build.feat.level=1;build.feat.slot=0;build.feat.change(m.feats.rcs.id,1)}build.domain.change(m.domain[0].id,0,1);build.domain.change(m.domain[1].id,1,1);if(m.school!==undefined){build.school.change(m.school.id,1)}if(m.familiar!==undefined){n=m.familiar.length;for(l=0;l<n;l++){if(m.familiar[l]===null||m.familiar[l]===undefined||m.familiar[l].class_level===undefined){continue}p=build.classes.findLevelByClassLevel(l,m.familiar[l].class_level);if(p!=false){build.familiar.level=p;build.familiar.change(m.familiar[l].id,1)}}}if(m.animal!==undefined){n=m.animal.length;for(l=0;l<n;l++){if(m.animal[l]===null||m.animal[l]===undefined||m.animal[l].class_level===undefined){continue}p=build.classes.findLevelByClassLevel(l,m.animal[l].class_level);if(p!=false){build.animal.level=p;build.animal.change(m.animal[l].id,1)}}}if(m.skills!==undefined){var h;n=m.skills.length;for(l=0;l<n;l++){build.skills.change(m.skills[l].id,1)}for(l=0;l<n;l++){h=m.skills[l].points.length;for(g=1;g<h;g++){c.skills[l].points[g]=m.skills[l].points[g]}}}builder.output.pause=false;builder.output.template.build_table();builder.output.template.skills_table();builder.ui.initialise();builder.output._cache=[];build.changed(1);builder.changeScope(b.SCOPE_BUILD);if(o.clone!==undefined&&o.clone==true){c.id=b.ID_NONE;c.name="Copy of "+(c.name.replace("Copy of ",""));if(o.clone_notify==true){sliph.message("Hey, this build doesn't belong to you!","I've created you your own copy to play with instead... guaranteed to be almost completely bug free!")}build.hasChanged=true;$(".button.save").removeClass("disabled").find(".hover").html("<strong>Save Changes</strong> made to the build")}else{build.hasChanged=false;$(".button.save").addClass("disabled").find(".hover").html("Nothing to Save")}builder.history.store=[];builder.history.index=0;builder.history.updateLabel()}})};builderEvents.prototype.save=function(n,e){if(n===undefined){n=false}builder.build.name=String(builder.build.name);if(builder.build.name.trim()==""){sliph.message("Oh Noes!","You forgot to give the build a name!",[{label:"Okay",bind:13,callback:function(){sliph.closeMessage(function(){build.info.show()})}}]);return}var t=builder.constant;var h=builder.rules;var g=builder.summary;var v=builder.build;builder.log("EVENT","Saving Build");if(builder.importing!=true){$(window).scrollTop(0);$("#builder_processing").html("Saving Build...").show()}var q=h.max_level;var w=g.classes.fetch(q);var s=g.attacks.fetch(q);var z=g.spell.fetch(q);var b=g.caster.fetch(q);var c=g.spell_dc.fetch(q);var a=g.abilities.fetch(q);var l=g.saves.fetch(q);var u=[0,0,0,0,0,0,0,0,0,0];var r,p;for(r=0;r<c.length;r++){if(c[r]===undefined){continue}p=10;while(p--){if(c[r].schools[p].value>u[p]){u[p]=c[r].schools[p].value}}}var y=0;var x=g.resistance.fetch(q);if(x[t.RESIST_TYPE_SPELL]!==undefined){y=x[t.RESIST_TYPE_SPELL].value}var m=[];var f,o;for(r=1;r<=q;r++){f=v.feats.auto[r].length;for(p=0;p<f;p++){if(!m.find(v.feats.auto[r][p].id)){m.push(v.feats.auto[r][p].id)}}if(v.feats.normal[r]!==undefined){for(p in v.feats.normal[r]){if(!m.find(v.feats.normal[r][p].id)){m.push(v.feats.normal[r][p].id)}}}for(o in v.feats.bonus){if(v.feats.bonus[o][r]!==undefined){for(p in v.feats.bonus[o][r]){if(!m.find(v.feats.bonus[o][r][p].id)){m.push(v.feats.bonus[o][r][p].id)}}}}for(o in v.feats.subselect){if(v.feats.subselect[o][r]!==undefined){for(p in v.feats.subselect[o][r]){if(!m.find(v.feats.subselect[o][r][p].id)){m.push(v.feats.subselect[o][r][p].id)}}}}if(v.feats.qtm.id!=t.ID_NONE){if(!m.find(v.feats.qtm.id)){m.push(v.feats.qtm.id)}}}m="|"+m.join("|")+"|";if(w.order[0]===undefined){w.order[0]={id:0,levels:0,label:"No Base Class",icon:"ia_use"}}var d={level:q,class_string:w.string,class_string_short:w.string_short,class1_id:w.order[0].id,class1_level:w.order[0].levels,class1_string:w.order[0].label,class1_icon:w.order[0].icon,class2_id:(w.order[1]!==undefined)?w.order[1].id:-1,class2_level:(w.order[1]!==undefined)?w.order[1].levels:0,class3_id:(w.order[2]!==undefined)?w.order[2].id:-1,class3_level:(w.order[2]!==undefined)?w.order[2].levels:0,class4_id:(w.order[3]!==undefined)?w.order[3].id:-1,class4_level:(w.order[3]!==undefined)?w.order[3].levels:0,race:v.race.id,race_string:v.race.label,alignment:v.alignment.id,bab:g.bab.fetch(q).value,dual_wield:(s.two_weapon==true)?1:0,attacks_melee:(s.two_weapon==true)?s.melee.dual_main.total+s.melee.dual_off.total:s.melee.main_hand.total,attacks_ranged:s.ranged.main_hand.total,melee_ab:(s.two_weapon==true)?s.melee.dual_main.scores[0]:s.melee.main_hand.scores[0],melee_touch_ab:s.melee.touch.scores[0],ranged_ab:s.ranged.main_hand.scores[0],ranged_touch_ab:s.ranged.touch.scores[0],arcane_spell:z.arcane.high,arcane_caster:b.arcane.high,divine_spell:z.divine.high,divine_caster:b.divine.high,invoke_spell:z.invoke.high,invoke_caster:b.invoke.high,dc_general:u[0],dc_abjuration:u[1],dc_conjuration:u[2],dc_divination:u[3],dc_enchantment:u[4],dc_evocation:u[5],dc_illusion:u[6],dc_necromancy:u[7],dc_transmutation:u[8],dc_invocation:u[9],ability_str:a[t.ABILITY_STR].value,ability_dex:a[t.ABILITY_DEX].value,ability_con:a[t.ABILITY_CON].value,ability_int:a[t.ABILITY_INT].value,ability_wis:a[t.ABILITY_WIS].value,ability_cha:a[t.ABILITY_CHA].value,save_fort:l[t.SAVING_THROW_FORT].value,save_refl:l[t.SAVING_THROW_REFL].value,save_will:l[t.SAVING_THROW_WILL].value,armor:g.armor.fetch(q).total,spell_resist:y,skill_points:g.skills.fetchPoints(q).total,hit_points:g.hp.fetch(q).value,feats:m,xp_penalty:g.xp_penalty.fetch(q).value,ecl:v.race.ecl};$.ajax({type:"POST",dataType:"json",data:{event:"save_build",json:JSON.stringify({game_version:builder.game_version,builder_version:builder.version,member_id:sliph.member.id,searchable:d,build:builder.build})},beforeSend:function(){$("body").css("cursor","wait")},complete:function(){$("body").css("cursor","");$("#builder_processing").hide()},error:function(A,k,j){console.log(A);sliph.message("AJAX Tanty!","Failed to save build!")},success:function(j){if(j.result==false){sliph.message("Oh Noes!",j.errors.join("<br>"));return false}if(builder.importing!=true){builder.build.id=j.data.build_id;build.hasChanged=false;$(".button.save").addClass("disabled").find(".hover").html("Nothing to Save");if(n==true){sliph.message("Success!","Your build has been saved",[{label:"Okay",bind:13,callback:function(){sliph.closeMessage();document.location=builder.directory.url}}])}else{sliph.message("Success!","Your build has been saved")}}if(e!==undefined){e()}}})};builderEvents.prototype.fetchTags=function(){builder.log("event","Importing Build Tags");$.ajax({type:"POST",dataType:"json",data:{event:"fetchTags"},error:function(c,b,a){alert("AJAX Tanty: Failed to import build tags!")},success:function(a){builder.tags=a;builder.log("event","Import Complete")}})};builder.events=new builderEvents();builder.tick("Build Validator");buildValidator=function(){this.valid=true;this.errors=[]};buildValidator.prototype.error=function(b,a){this.valid=false;if(this.errors[b]===undefined){this.errors[b]=[]}this.errors[b].push(a)};buildValidator.prototype.warning=function(b,a){if(this.errors[b]===undefined){this.errors[b]=[]}this.errors[b].push(a)};buildValidator.prototype.output=function(){var e=[];var a='<div class="validation">';var d;for(var b in this.errors){if(["find","high","low","fetch"].find(b)){continue}d="- "+this.errors[b].join("<br>- ");e.push("<p><strong>"+b+"</strong>"+d+"</p>")}var c=(this.valid==true)?" warning":"";return(e.length)?'<div class="validation'+c+'"><div>'+e.join("")+"</div></div>":""};builder.tick("User Interface Enhancements");var builderUI=function(){};builderUI.prototype.initialise=function(){$(function(){builder.ui.bindKeys();builder.ui.draggableClass()})};builderUI.prototype.draggableClass=function(){$("#table_build .class").draggable({revert:true,revertDuration:50,scope:"class",delay:200,start:function(a,b){$(this).attr("data-dragging",1)},stop:function(a,b){$(this).removeAttr("data-dragging")}}).droppable({accept:"a.class",scope:"class",drop:function(a,j){var f=builder.constant;var l=builder.rules;var h=builder.build;var g=parseInt($(j.draggable).attr("data-index"));var k=parseInt($(a.target).attr("data-index"));var d=h.level[g].class_id;var m=l.max_level;build.classes.history=[];for(var e=1;e<=m;e++){build.classes.history[e]=h.level[e].class_id}var b=g;var c=k;if(g>k){for(var e=b;e>c;e--){build.classes.level=e;build.classes.change(h.level[e-1].class_id,1,true)}}else{for(var e=b;e<c;e++){build.classes.level=e;build.classes.change(h.level[e+1].class_id,1,true)}}builder.history.ignore=true;build.classes.level=k;build.classes.change(d,1,true);builder.history.ignore=false;builder.history.add(f.HISTORY_SCOPE_CLASS_BATCH);build.classes.calculateSaves();build.changed((g<k?g:k))}})};builderUI.prototype.draggableFeats=function(){return;$("#table_build .classFeat").draggable({revert:true,revertDuration:50,scope:"feat",start:function(a,b){$(this).attr("data-dragging",1)},stop:function(a,b){$(this).removeAttr("data-dragging")}}).droppable({accept:"a.classFeat",scope:"feat",drop:function(a,j){var f=builder.constant;var l=builder.rules;var h=builder.build;var g=$(j.draggable);var k=$(a.target);return;var d=h.level[g].class_id;var m=l.max_level;build.classes.history=[];for(var e=1;e<=m;e++){build.classes.history[e]=h.level[e].class_id}var b=g;var c=k;if(g>k){for(var e=b;e>c;e--){build.classes.level=e;build.classes.change(h.level[e-1].class_id,1,true)}}else{for(var e=b;e<c;e++){build.classes.level=e;build.classes.change(h.level[e+1].class_id,1,true)}}builder.history.ignore=true;build.classes.level=k;build.classes.change(d,1);builder.history.ignore=false;builder.history.add(f.HISTORY_SCOPE_CLASS_BATCH)}})};builderUI.prototype.clickAbility=function(d,f,e){if(d.shiftKey==true){var a=builder.rules;var c=builder.build;for(var b=0;b<a.ability_selection.length;b++){if(a.ability_selection[b]<f){continue}c.level[a.ability_selection[b]].ability=e}return build.changed(a.ability_selection[0])}else{build.ability.change(f,e)}};builderUI.prototype.clickEpicRelevel=function(b,a,c){build.ability.changeEpicRelevel(a,c)};builderUI.prototype.clickROTExtraAbility=function(a,b){build.ability.changeROTExtraAbility(b)};builderUI.prototype.resetEpicRelevel=function(b,a){builder.build.ability.ROT[a]=[0,0,0,0,0,0];build.changed(builder.rules.rot_epic_relevel)};builderUI.prototype.resetROTExtraAbilities=function(a){builder.build.ability.ROTE=[0,0,0,0,0,0];build.changed()};builderUI.prototype.bindKeys=function(){return;var a=builder.constant;$(window).unbind("keypress");switch(build.scope){case a.SCOPE_BUILD:$(window).bind("keypress",function(b){switch(b.keyCode){case 26:if(b.ctrlKey==true){builder.history.undo()}break;case 25:if(b.ctrlKey==true){builder.history.redo()}break}});break;case a.SCOPE_SKILLS:break;case a.SCOPE_SPELLS:break}};builderUI.prototype.bindExitWarning=function(){window.onbeforeunload=function(a){if(build.hasChanged==false||build.ignoreExitWarning==true){return null}a=a||window.event;if(a){a.returnValue="Changes to this build will be lost."}return"Changes to this build will be lost."}};builder.ui=new builderUI();builder.ui.bindExitWarning();builder.tick("Build Summary");var builderSummary=function(){};builderSummary.prototype._cache=[];builderSummary.prototype._fetch=[];builderSummary.prototype.initialise=function(){var a=builder.rules.max_store_level;this._cache=[];for(var b=1;b<=a;b++){this._cache[b]={abilities:{},saves:{},feats:[],caster:{},spell:{},skill:{},bab:{}}}};builderSummary.prototype.cache=function(d){var a=builder.rules;var b=a.max_level;for(var c=1;c<=b;c++){this._fetch[c]={abilities:[],saves:[],skills:[],feats:[],caster:[],spell:[],skill:[],bab:[]}}this.feats.cache(d);a.compile();this.abilities.cache(d);this.saves.cache(d)};builderSummary.prototype.fetchRules=function(p,n){var m=builder.constant;var s=builder.rules;if(n===undefined){n=m.FEAT_TYPE_ANY}var a=p;var r=[];var c=[];var l=[];var f,e,q,h,d,o;o=n;while(a>0){o=(a==p)?n:m.FEAT_TYPE_ANY;h=this.feats.fetch(p,o);d=s.compiled[a];switch(o){case m.FEAT_TYPE_ANY:q=d.normal;f=q.length;while(f--){if(!l.find(q[f].id)){l.push(q[f].id);if(q[f].ignore!==undefined){e=q[f].ignore.length;while(e--){c.push(q[f].ignore[e])}}r.push(q[f])}}case m.FEAT_TYPE_NORMAL:q=d.bonus;f=q.length;while(f--){if(!l.find(q[f].id)){l.push(q[f].id);if(q[f].ignore!==undefined){e=q[f].ignore.length;while(e--){c.push(q[f].ignore[e])}}r.push(q[f])}}case m.FEAT_TYPE_QUICK_TO_MASTER:case m.FEAT_TYPE_BONUS:q=d.subselect;f=q.length;while(f--){if(!l.find(q[f].id)){l.push(q[f].id);if(q[f].ignore!==undefined){e=q[f].ignore.length;while(e--){c.push(q[f].ignore[e])}}r.push(q[f])}}case m.FEAT_TYPE_SUBSELECT:default:q=d.auto;f=q.length;while(f--){if(!l.find(q[f].id)){l.push(q[f].id);if(q[f].ignore!==undefined){e=q[f].ignore.length;while(e--){c.push(q[f].ignore[e])}}r.push(q[f])}}}a--}var b=[];var g=r.length;while(g--){if(c.find(r[g].id)){continue}b.push(r[g])}return b};builderSummary.prototype.abbreviate=function(a){switch(a){case 0:return"Brb";case 1:return"Brd";case 2:return"Cle";case 3:return"D";case 4:return"F";case 5:return"M";case 6:return"Pal";case 7:return"Ra";case 8:return"Ro";case 9:return"Sor";case 10:return"Wiz";case 27:return"SD";case 28:return"HA";case 29:return"AA";case 30:return"Asn";case 31:return"BG";case 32:return"DC";case 33:return"WM";case 34:return"PM";case 36:return"DD";case 37:return"RDD";case 39:return"Wlk";case 40:return"AT";case 43:return"FB";case 45:return"SF";case 46:return"STA";case 47:return"NN";case 50:return"Dls";case 51:return"WP";case 52:return"EK";case 53:return"RWT";case 54:return"ASC";case 55:return"SS";case 56:return"SL";case 57:return"IB";case 58:return"FS";case 59:return"SB";case 60:return"DG";case 61:return"HW";case 106:return"Hos";case 107:return"WoD";case 108:return"BSin";case 109:return"SSin";case 110:return"Temp";case 111:return"BFZ";case 112:return"ShinB";case 113:return"SwifB";case 114:return"FM";case 115:return"NW";case 116:return"T";case 117:return"ED";case 118:return"EA";case 119:return"DS";case 120:return"AK";case 121:return"NW";case 122:return"Mage";case 123:return"LoT";case 124:return"CL";case 125:return"LT";case 126:return"CW";case 127:return"SH";case 128:return"DL";case 129:return"NI";case 130:return"MR";case 131:return"Ward";case 132:return"KT";case 133:return"Stalk";case 134:return"Slay";case 135:return"DS";case 136:return"FotF";case 137:return"CotSF";case 142:return"Av";case 166:return"DCom";case 180:return"EW";case 181:return"WD";case 182:return"DB";case 183:return"Opt"}return"??"};builder.summary=new builderSummary();builder.tick("Build Summary: Output");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.output={element:"output_summary",linked:true,manual_stored:{},close:function(){$("body").css("overflow","").css("width","");$("#output_summary").hide()},update:function(L,w){if(L===undefined){L=false}if(w===undefined){w="#output_summary"}var G=a.max_level;if(L==true&&this.manual_stored[G]!==undefined){$(w).html(this.manual_stored[G]);return}if(!L){var J=(window.innerHeight)?[window.innerWidth,window.innerHeight]:[document.documentElement.clientWidth,document.documentElement.clientHeight];$("body").bind("keyup",function(N){if(N.keyCode==27){$("body").unbind("keyup");d.output.close()}})}var H,D="";var j="";var h=d.abilities.fetch(1,b.FEAT_TYPE_AUTO);var s=d.abilities.fetch(G);for(H=0;H<a.abilities.length;H++){j+='<tr><td class="label">'+a.abilities[H].label+"</td><td>"+h[H].value+"</td><td>"+s[H].value+"</td><td>"+this.formatModifier(s[H].modifier,true)+"</td></tr>"}var r=d.classes.fetch(G);var K=[];H=0;while(H<r.order.length){if(r.order[H]!==undefined){K.push('<a class="label"'+this.link("library/classes/",r.order[H].id)+">"+r.order[H].label+"</a> ("+r.order[H].levels+")")}H++}var l="";var p=51;var B;var u=d.resistance.fetch(G);for(H in u){if(u[H].value==0){continue}B=(u[H].value==-1)?"Immune":u[H].value;l+='<div class="stat" style="z-index:'+p+';"><div class="value">'+B+this.effects(u[H].effects,"resistance")+'</div><div class="label">'+u[H].label+"</div></div>";p--}var o=d.reduction.fetch(G);for(H in o){if(o[H].value==0){continue}l+='<div class="stat" style="z-index:'+p+';"><div class="value">'+o[H].value+"/"+o[H].label+this.effects(o[H].effects)+'</div><div class="label">Damage Reduction: </div></div>';p--}if(l==""){l='<div class="stat text" style="z-index:'+p+';"><div class="label">None</div></div>'}var M=d.hp.fetch(G);var t=d.bab.fetch(G);var n=d.attacks.fetch(G);var g=d.armor.fetch(G);var m=d.saves.fetch(G);var q=d.caster.fetch(G);var y=d.spell.fetch(G);var x=d.xp_penalty.fetch(G);var k=(q.arcane.high>0||q.divine.high>0||q.invoke.high>0);p=78;var f=d.spell_dc.fetch(G);var v="";H=f.length;while(H--){if(f[H]!==undefined){v+='<div class="stat" style="z-index:'+p+';"><div class="value">DC '+f[H].high+this.effects(f[H].schools,"spell_dc",f[H].id)+' + Spell Level</div><div class="label">'+f[H].label+"</div></div>";p--}}var F=d.skills.fetchPoints(G);var C='<div class="stat half" style="z-index:78;"><div class="value">'+F.total+this.effects(F.classes,"skill_points")+'</div><div class="label">Total Points</div></div><div class="stat half right no_menu" style="z-index:78;"><div class="value">'+F.unused+'</div><div class="label">Unspent Points</div></div>';var E=d.skills.fetch(G);var e=E.length;p=77;for(H=0;H<e;H++){if(E[H].id>100){E[H].label="Any Skill"}C+='<div class="stat clear" style="z-index:'+p+';"><div class="value">'+E[H].value_raw+" ("+E[H].value+")"+this.effects(E[H].effects)+'</div><div class="label">'+E[H].label+"</div></div>";p--}var I=builder.directory.icons;D+='<h2><a class="close" onclick="builder.summary.output.close();"></a>Summary</h2><div class="build_strings">'+K.join(", ")+'</div><table class="abilities"><thead><tr><th>Ability</th><th>Base</th><th>Final</th><th>Mod</th></tr></thead><tbody>'+j+'</tbody></table><a class="block"'+this.link("library/races/",c.race.base_id)+'><div class="icon" style="background-image:url('+I+"40x40/"+c.race.icon+'.png);"></div><span>'+c.race.label+'</span></a><a class="block"'+this.link("library/alignments/",c.alignment.id)+'><div class="icon" style="background-image:url('+I+"40x40/"+c.alignment.icon+'.png);"></div><span>'+c.alignment.label+'</span></a><a class="block"'+this.link("library/deities/",false,"#item_"+c.deity.id)+'><div class="icon" style="background-image:url('+I+"40x40/"+c.deity.icon+'.png);"></div><span>'+c.deity.label+'</span></a><a class="block"'+this.link("library/backgrounds/",c.background.id)+'><div class="icon" style="background-image:url('+I+"40x40/"+c.background.icon+'.png);"></div><span>'+c.background.label+'</span></a><div style="clear:left;"><br></div><div style="padding-top:6px;"><div class="stat hp" style="z-index:99;"><div class="value">'+M.value+this.effects(M.effects)+'</div><div class="label">Hit Points</div></div><div class="stat armor" style="z-index:98;"><div class="value">'+g.total+this.effects(g,"armor")+'</div><div class="label">Armor</div></div><div class="stat penalty" style="z-index:97;"><div class="value">'+x.value+this.effects(x.effects)+'%</div><div class="label">XP Penalty</div></div><div class="stat ecl" style="z-index:96;"><div class="value">+'+c.race.ecl+this.effects([[c.race.label,c.race.ecl]])+'</div><div class="label">ECL</div></div></div><div style="clear:left;"><br></div><div class="block_50 right"><h2>Saving Throws</h2><div class="stat" style="z-index:57;"><div class="value">'+m[b.SAVING_THROW_FORT].value+this.effects(m[b.SAVING_THROW_FORT].effects)+'</div><div class="label">'+m[b.SAVING_THROW_FORT].label+'</div></div><div class="stat" style="z-index:56;"><div class="value">'+m[b.SAVING_THROW_REFL].value+this.effects(m[b.SAVING_THROW_REFL].effects)+'</div><div class="label">'+m[b.SAVING_THROW_REFL].label+'</div></div><div class="stat" style="z-index:54;"><div class="value">'+m[b.SAVING_THROW_WILL].value+this.effects(m[b.SAVING_THROW_WILL].effects)+'</div><div class="label">'+m[b.SAVING_THROW_WILL].label+'</div></div><div class="stat" style="z-index:53;"><div class="value">'+m[b.SAVING_THROW_SPELL].value+this.effects(m[b.SAVING_THROW_SPELL].effects)+'</div><div class="label">'+m[b.SAVING_THROW_SPELL].label+'</div></div><div class="stat" style="z-index:52;"><div class="value">'+m.high+this.effects(m,"saves")+'</div><div class="label">More</div></div></div><div class="block_50"><h2>Attack Bonuses</h2><div class="stat" style="z-index:92;"><div class="value">'+t.value+this.effects(t.effects)+'</div><div class="label">Base Attack Bonus</div></div><div class="stat half right" style="z-index:91;"><div class="value">'+this.formatValue(n.melee.touch.value+t.value)+this.effects(n.melee.touch.effects)+'</div><div class="label">Melee Touch</div></div>'+(n.two_weapon==false?'<div class="stat half" style="z-index:90;"><div class="value">'+this.formatValue(n.melee.main_hand.value+t.value)+this.effects(n.melee.main_hand.effects)+'</div><div class="label">Melee</div></div>':'<div class="stat half" style="z-index:90;"><div class="value">'+this.formatValue(n.melee.dual_main.value+t.value)+'<div class="effects"><ul><li><span class="sub"></span><span>'+(n.melee.dual_main.value+t.value)+"</span>Main Hand"+this.effects(n.melee.dual_main.effects)+'</li><li><span class="sub"></span><span>'+(n.melee.dual_off.value+t.value)+"</span>Off Hand"+this.effects(n.melee.dual_off.effects)+'</li></ul></div></div><div class="label">Melee</div></div>')+'<div class="stat half right" style="z-index:89;"><div class="value">'+this.formatValue(n.ranged.touch.value+t.value)+this.effects(n.ranged.touch.effects)+'</div><div class="label">Ranged Touch</div></div><div class="stat half" style="z-index:88;"><div class="value">'+this.formatValue(n.ranged.main_hand.value+t.value)+this.effects(n.ranged.main_hand.effects)+'</div><div class="label">Ranged</div></div>'+(n.two_weapon==false?'<div class="stat text" style="z-index:87;margin-right:0px"><div class="label">Main Hand</div><div class="value">'+n.melee.main_hand.string+'</div><div style="clear:left;"></div></div>':'<div class="stat text" style="z-index:87;margin-right:0px"><div class="label">Main Hand</div><div class="value">'+n.melee.dual_main.string+'</div><div style="clear:left;"></div></div><div class="stat text" style="z-index:86;margin-right:0px"><div class="label">Off Hand</div><div class="value">'+n.melee.dual_off.string+'</div><div style="clear:left;"></div></div>')+'<div class="stat text" style="z-index:85;margin-right:0px"><div class="label">Ranged</div><div class="value">'+n.ranged.main_hand.string+'</div><div style="clear:left;"></div></div></div><div class="clear"></div><div class="block_50 right"><h2>Resistances & Reductions</h2>'+l+'</div><div class="block_50"><h2>Spell Casting</h2>'+(k==true?(q.arcane.high>0?'<div class="stat half right no_menu" style="z-index:84;"><div class="value">'+this.convertSpellLevel("arcane",y.arcane.high,y.arcane.high_ability)+this.effects(y.arcane.effects)+'</div><div class="label">Spell Level</div></div><div class="stat half" style="z-index:83;"><div class="value">'+q.arcane.high+this.effects(q.arcane.classes,"caster")+'</div><div class="label">Arcane Caster</div></div>':"")+(q.divine.high>0?'<div class="stat half right no_menu" style="z-index:82;"><div class="value">'+this.convertSpellLevel("divine",y.divine.high,y.divine.high_ability)+this.effects(y.divine.effects)+'</div><div class="label">Spell Level</div></div><div class="stat half" style="z-index:81;"><div class="value">'+q.divine.high+this.effects(q.divine.classes,"caster")+'</div><div class="label">Divine Caster</div></div>':"")+(q.invoke.high>0?'<div class="stat half right no_menu" style="z-index:80;"><div class="value">'+this.convertSpellLevel("invoke",y.invoke.high,y.invoke.high_ability)+this.effects(y.invoke.effects)+'</div><div class="label">Grade</div></div><div class="stat half" style="z-index:79;"><div class="value">'+q.invoke.high+this.effects(q.invoke.classes,"caster")+'</div><div class="label">Invoker Level</div></div>':""):'<div class="stat half no_menu" style="z-index:79;"><div class="label">None</div></div>')+'<div style="clear:left;"></div>'+v+"<br><h2>Skill Points & Selection</h2>"+C+"</div>"+(L==true?'<div class="clear"></div>':'<div class="clear_bottom"></div>');D='<div class="inner_frame">'+D+"</div>";if(!L){$("#output_summary .dialog .inner").html(D);$("#output_summary").show();var z=J[1]-(J[1]/4);var A=680;$("#output_summary .dialog .inner").css("height",z);$("#output_summary .dialog").css("left",(J[0]/2)-(A/2)).css("top",(J[1]/2)-(z/2));$("body").css("width",$("body").width()).css("overflow","hidden")}else{this.manual_stored[G]=D;$(w).html(D)}},formatValue:function(e){if(e>=0){return"+"+e}return e},convertSpellLevel:function(g,j,h){switch(g){case"arcane":case"divine":if(h===undefined){h=j}var e=(j==1)?"Cantrip":(j==0?"None":(j-1));if(h<j){var f=(h==1)?"Cantrip":(h<=0?"None":(h-1));e+=" ("+f+")"}return e;case"invoke":if(j<=2){return"Least"}if(j<=3){return"Lesser"}if(j<=4){return"Greater"}if(j<=5){return"Dark"}default:return"None"}},effects:function(f,o,n){var g="";var k=0;var j,e,h;if(o!==undefined){switch(o){case"spell_dc":if(n===undefined){n=b.ID_NONE}var p=d.classes.fetch(a.max_level);var l=["General","Abjuration","Conjuration","Divination","Enchantment","Evocation","Illusion","Necromancy","Transmutation","Invocation"];k=0;while(k<=9){if(f[k].effects.length>0){if(k==b.SCHOOL_INVOKER&&![39,61].find(n)){k++;continue}h=this.effects(f[k].effects);g+='<li><span class="sub"></span><span>'+f[k].value+"</span>"+l[k]+h+"</li>"}k++}break;case"armor":var m=[1,2,4,8,16,32];k=0;while(k<m.length){e="";if(f[m[k]].value>0){e=' class="positive"'}if(f[m[k]].value<0){e=' class="negative"'}j=(f[m[k]].value>=0)?"+"+f[m[k]].value:f[m[k]].value;if(f[m[k]].effects.length>0){h=this.effects(f[m[k]].effects);g+="<li"+e+'><span class="sub"></span><span>'+j+"</span>"+f[m[k]].label+h+"</li>"}else{g+="<li"+e+'><span class="nosub"></span><span>'+j+"</span>"+f[m[k]].label+"</li>"}k++}break;case"caster":for(k=0;k<f.length;k++){if(f[k]===undefined){continue}if(f[k].effects.length>0){h=this.effects(f[k].effects);g+='<li class="positive"><span class="sub"></span><span>'+f[k].value+"</span>"+f[k].label+h+"</li>"}else{g+='<li class="positive"><span class="nosub"></span><span>'+f[k].value+"</span>"+f[k].label+"</li>"}}break;case"saves":var m=[b.SAVING_THROW_SPELL,b.SAVING_THROW_DEATH,b.SAVING_THROW_MIND,b.SAVING_THROW_POISON,b.SAVING_THROW_FEAR,b.SAVING_THROW_DISEASE,b.SAVING_THROW_TRAPS];k=0;while(k<m.length){if(f[m[k]].effects.length>0){h=this.effects(f[m[k]].effects);g+='<li><span class="sub"></span><span>'+f[m[k]].value+"</span>"+f[m[k]].label+h+"</li>"}else{g+='<li><span class="nosub"></span><span>'+f[m[k]].value+"</span>"+f[m[k]].label+"</li>"}k++}if(g!=""){g='<div class="effects force_left"><ul>'+g+"</ul></div>"}return g;case"resistance":while(k<f.length){e="";if(f[k][1]>0){e=' class="positive"'}j=(f[k][1]==-1)?"Immune":"+"+f[k][1];g+="<li"+e+"><span>"+j+"</span>"+f[k][0]+"</li>";k++}break;case"skill_points":while(k<f.length){if(f[k]===undefined){k++;continue}g+="<li><span>+"+f[k].total+"</span>"+f[k].label+"</li>";k++}break}}else{while(k<f.length){e="";if(f[k][1]>0){e=' class="positive"'}if(f[k][1]<0){e=' class="negative"'}j=(f[k][1]>=0)?"+"+f[k][1]:f[k][1];g+="<li"+e+"><span>"+j+"</span>"+f[k][0]+"</li>";k++}}if(g!=""){g='<div class="effects"><ul>'+g+"</ul></div>"}return g},link:function(f,h,g){if(this.linked==false){return""}var e=builder.directory.url+f+"?";if(h!==undefined&&h!==false){e+=h+"&"}e+="g="+builder.game_version;if(g!==undefined){e+=g}return' target="_blank" href="'+e+'"'},formatModifier:function(e,f){if(f===undefined){f=false}var g=false;if(e<0){g="negative"}if(e>0){g="positive"}if(f&&e>=0){e="+"+e}if(g!=false){e='<span class="'+g+'">'+e+"</span>"}return e}}})();builder.tick("Build Summary: Feats");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.feats={merge:function(e,n,m){if(!n.length){return}var p=d._cache[e].feats;var f=a.auto_feat_requirements;var o=a.feat_rename;var h,g,l=n.length;while(l--){if(n[l]===undefined){continue}h=n[l].length;skip_feat:while(h--){if(n[l][h].id===undefined){continue skip_feat}if(n[l][h]===undefined){continue skip_feat}if(n[l][h].type==b.FEAT_TYPE_AUTO){g=f.length;while(g--){if(f[g].feats.find(n[l][h].id)){if(!m.find(f[g].requires)){continue skip_feat}}}}if(n[l][h].id!=b.ID_NONE){m.push(n[l][h].id);if(o[n[l][h].id]!==undefined){n[l][h].label=o[n[l][h].id]}p.push(n[l][h]);p[p.length-1].slot=h}}}},cache:function(j){builder.log("sum","Caching Feats ("+j+")");var g=a.max_level;var h,f;var e=[];while(g>=j){d._cache[g].feats=[];f=c.feats;if(g==1){this.merge(1,[c.race.feats],e)}this.merge(g,[c.feats.auto[g],build.feat.get(b.FEAT_TYPE_COMBAT_STYLE,g,-1),build.feat.get(b.FEAT_TYPE_NORMAL,g,-1),build.feat.get(b.FEAT_TYPE_BONUS,g,-1),build.feat.get(b.FEAT_TYPE_SUBSELECT,g,-1)],e);if(g==1){if(this.have(a.featid_quick_to_master,1,b.FEAT_TYPE_AUTO)){this.merge(g,[build.feat.get(b.FEAT_TYPE_QUICK_TO_MASTER,g,-1)],e)}}g--}return a.runScripts(b.SCRIPT_SUMMARY_CACHE_FEATS,c.feats.auto)},fetch:function(f,q,s,e,t){if(q===undefined){q=b.FEAT_TYPE_ANY}if(s===undefined){s=false}if(e===undefined){e=false}if(t===undefined){t=0}var m=[];var h=(s)?1:f;var j=f;var l,u,k,n,p;while(j>=h){u=d._cache[j].feats;l=u.length;while(l--){k=(e)?u[l].id:u[l];if(j==f){n=u[l].type;p=u[l].slot;switch(q){case b.FEAT_TYPE_ANY:if(n==b.FEAT_TYPE_NORMAL){m.push(k)}case b.FEAT_TYPE_NORMAL:if(t>0&&n==b.FEAT_TYPE_NORMAL&&p<t){m.push(k)}if(n==b.FEAT_TYPE_BONUS){m.push(k)}if(n==b.FEAT_TYPE_QUICK_TO_MASTER){m.push(k)}case b.FEAT_TYPE_BONUS:if(t>0&&n==b.FEAT_TYPE_BONUS&&p<t){m.push(k)}case b.FEAT_TYPE_QUICK_TO_MASTER:if(n==b.FEAT_TYPE_SUBSELECT){m.push(k)}case b.FEAT_TYPE_SUBSELECT:if(t>0&&n==b.FEAT_TYPE_SUBSELECT&&p<t){m.push(k)}default:if(n==b.FEAT_TYPE_AUTO){m.push(k)}}}else{m.push(k)}}j--}var o,r=c.familiar;var g=false;for(var l in r){o=r[l];if(o===null||o===undefined){continue}if(o.id==b.ID_NONE||o.feat===undefined){continue}if(g!=false&&g<o.level){continue}m.push(o.feat)}return m},category:function(j,k,e){if(e===undefined){e=b.FEAT_TYPE_ANY}var h=0;var f=this.fetch(k,e,true,false);var g=f.length;while(g--){if(f[g].category==j){h++}}return h},have:function(j,h,e,f,g){if(j==a.featid_shadow_theif){return true}if(g===undefined){g=0}if(h===undefined){h=a.max_level}if(f===undefined){f=false}if(e===undefined){e=b.FEAT_TYPE_ANY}return this.fetch(h,e,(f==true)?false:true,true,g).find(j)}}})();builder.tick("Build Summary: Saving Throws");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.saves={cache:function(f){builder.log("sum","Caching Saving Throws ("+f+")");var h=[];var m=[];var g=[];var o=a.max_level;var p,e,k,n;for(var l=1;l<=o;l++){d._cache[l].saves={fortitude:{value:0,effects:[]},reflex:{value:0,effects:[]},will:{value:0,effects:[]},rules:{any:[],normal:[],bonus:[],subselect:[],auto:[]}};e=c.level[l];p=d._cache[l].saves;if(!h.find(e.class_id)){h.push(e.class_id);m.push(e.class_label)}g[e.class_id]=e.save;for(k=0;k<h.length;k++){p.fortitude.value+=g[h[k]].fortitude;p.fortitude.effects.push([m[k],g[h[k]].fortitude]);p.reflex.value+=g[h[k]].reflex;p.reflex.effects.push([m[k],g[h[k]].reflex]);p.will.value+=g[h[k]].will;p.will.effects.push([m[k],g[h[k]].will])}p.rules.any=d.fetchRules(l,b.FEAT_TYPE_ANY);p.rules.normal=d.fetchRules(l,b.FEAT_TYPE_NORMAL);p.rules.bonus=d.fetchRules(l,b.FEAT_TYPE_BONUS);p.rules.subselect=d.fetchRules(l,b.FEAT_TYPE_SUBSELECT);p.rules.auto=d.fetchRules(l,b.FEAT_TYPE_AUTO)}},fetch:function(e,l){if(l===undefined){l=b.FEAT_TYPE_ANY}if(d._fetch[e].saves[l]!==undefined){return d._fetch[e].saves[l]}var o=d._cache[e].saves;var f=d.abilities.fetch(e,l);var g={};g[b.SAVING_THROW_FORT]={value:0,effects:[],label:"Fortitude"};g[b.SAVING_THROW_REFL]={value:0,effects:[],label:"Reflex"};g[b.SAVING_THROW_WILL]={value:0,effects:[],label:"Will"};var h;g[b.SAVING_THROW_FORT].value+=o.fortitude.value;h=0;while(h<o.fortitude.effects.length){g[b.SAVING_THROW_FORT].effects.push(o.fortitude.effects[h]);h++}g[b.SAVING_THROW_REFL].value+=o.reflex.value;h=0;while(h<o.reflex.effects.length){g[b.SAVING_THROW_REFL].effects.push(o.reflex.effects[h]);h++}g[b.SAVING_THROW_WILL].value+=o.will.value;h=0;while(h<o.will.effects.length){g[b.SAVING_THROW_WILL].effects.push(o.will.effects[h]);h++}if(f[b.ABILITY_CON].modifier!=0){g[b.SAVING_THROW_FORT].value+=f[b.ABILITY_CON].modifier;g[b.SAVING_THROW_FORT].effects.push([a.abilities[b.ABILITY_CON].label,f[b.ABILITY_CON].modifier])}if(f[b.ABILITY_DEX].modifier!=0){g[b.SAVING_THROW_REFL].value+=f[b.ABILITY_DEX].modifier;g[b.SAVING_THROW_REFL].effects.push([a.abilities[b.ABILITY_DEX].label,f[b.ABILITY_DEX].modifier])}if(d.feats.have(2170)){if(f[b.ABILITY_CON].modifier!=0){g[b.SAVING_THROW_WILL].value+=f[b.ABILITY_CON].modifier;g[b.SAVING_THROW_WILL].effects.push([a.abilities[b.ABILITY_CON].label,f[b.ABILITY_CON].modifier])}}else{if(f[b.ABILITY_WIS].modifier!=0){g[b.SAVING_THROW_WILL].value+=f[b.ABILITY_WIS].modifier;g[b.SAVING_THROW_WILL].effects.push([a.abilities[b.ABILITY_WIS].label,f[b.ABILITY_WIS].modifier])}}g[b.SAVING_THROW_SPELL]={label:"Spell",value:0,effects:[]};g[b.SAVING_THROW_POISON]={label:"Poison",value:0,effects:[]};g[b.SAVING_THROW_DEATH]={label:"Death",value:0,effects:[]};g[b.SAVING_THROW_DISEASE]={label:"Disease",value:0,effects:[]};g[b.SAVING_THROW_FEAR]={label:"Fear",value:0,effects:[]};g[b.SAVING_THROW_MIND]={label:"Mind",value:0,effects:[]};g[b.SAVING_THROW_TRAPS]={label:"Traps",value:0,effects:[]};switch(l){case b.FEAT_TYPE_ANY:var n=o.rules.any;break;case b.FEAT_TYPE_NORMAL:var n=o.rules.normal;break;case b.FEAT_TYPE_BONUS:var n=o.rules.bonus;break;case b.FEAT_TYPE_SUBSELECT:var n=o.rules.subselect;break;case b.FEAT_TYPE_AUTO:var n=o.rules.auto;break;default:var n=[]}g=a.affect(g,b.AFFECT_SAVING_THROWS,n,e,l);g[b.SAVING_THROW_POISON].value+=g[b.SAVING_THROW_FORT].value;g[b.SAVING_THROW_POISON].effects.push(["Fortitude",g[b.SAVING_THROW_FORT].value]);g[b.SAVING_THROW_DEATH].value+=g[b.SAVING_THROW_FORT].value;g[b.SAVING_THROW_DEATH].effects.push(["Fortitude",g[b.SAVING_THROW_FORT].value]);g[b.SAVING_THROW_DISEASE].value+=g[b.SAVING_THROW_FORT].value;g[b.SAVING_THROW_DISEASE].effects.push(["Fortitude",g[b.SAVING_THROW_FORT].value]);g[b.SAVING_THROW_TRAPS].value+=g[b.SAVING_THROW_REFL].value;g[b.SAVING_THROW_TRAPS].effects.push(["Reflex",g[b.SAVING_THROW_REFL].value]);g[b.SAVING_THROW_FEAR].value+=g[b.SAVING_THROW_WILL].value;g[b.SAVING_THROW_FEAR].effects.push(["Will",g[b.SAVING_THROW_WILL].value]);g[b.SAVING_THROW_MIND].value+=g[b.SAVING_THROW_WILL].value;g[b.SAVING_THROW_MIND].effects.push(["Will",g[b.SAVING_THROW_WILL].value]);var j=d.skills.fetch(e);var k=j.length;for(h=0;h<k;h++){if(j[h].id==16){var m=Math.floor(j[h].value_raw/5);if(m>0){g[b.SAVING_THROW_SPELL].value+=m;g[b.SAVING_THROW_SPELL].effects.push(["Spellcraft",m])}break}}g.high=0;if(g[b.SAVING_THROW_DEATH].value>g.high){g.high=g[b.SAVING_THROW_DEATH].value}if(g[b.SAVING_THROW_MIND].value>g.high){g.high=g[b.SAVING_THROW_MIND].value}if(g[b.SAVING_THROW_SPELL].value>g.high){g.high=g[b.SAVING_THROW_SPELL].value}if(g[b.SAVING_THROW_POISON].value>g.high){g.high=g[b.SAVING_THROW_POISON].value}if(g[b.SAVING_THROW_FEAR].value>g.high){g.high=g[b.SAVING_THROW_FEAR].value}if(g[b.SAVING_THROW_DISEASE].value>g.high){g.high=g[b.SAVING_THROW_DISEASE].value}if(g[b.SAVING_THROW_TRAPS].value>g.high){g.high=g[b.SAVING_THROW_TRAPS].value}d._fetch[e].saves[l]=g;return g}}})();builder.tick("Build Summary: Skills");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.skills={cache:function(f){builder.log("sum","Caching Skill Gains ("+f+")");var p=a.max_level;var m=d.classes.fetch(p).classes;var q,e,h,o,g,n;var l=0;for(var k=1;k<=p;k++){e=c.level[k];q=d._cache[k].skill;g=e.class_id;n=m[g].skill;n+=Math.floor(d.abilities.fetch(k,b.FEAT_TYPE_AUTO)[b.ABILITY_INT].modifier);if(d.feats.have(a.featid_skilled,k)){n+=1}if(k==1){n=(n*4)}l+=n;d._cache[k].skill={gain:n,total:l}}},fetch:function(e,m,o){if(m===undefined){m=b.FEAT_TYPE_ANY}var h=[];var l=(c.skills!==undefined)?c.skills.length:0;var r=e;var g,f,n,p=0;for(g=0;g<l;g++){p=0;for(f=1;f<=r;f++){p+=c.skills[g].points[f]}if(p==0){continue}switch(c.skills[g].ability){case"str":n=b.ABILITY_STR;break;case"dex":n=b.ABILITY_DEX;break;case"con":n=b.ABILITY_CON;break;case"int":n=b.ABILITY_INT;break;case"wis":n=b.ABILITY_WIS;break;case"cha":n=b.ABILITY_CHA;break;default:n=false}h.push({id:c.skills[g].id,label:c.skills[g].label,icon:c.skills[g].icon,points:c.skills[g].points,value:p,value_raw:p,ability:n,effects:[]})}if(o===undefined){var k=d.abilities.fetch(e,m);l=h.length;for(g=0;g<l;g++){if(h[g].ability!==false){h[g].value+=k[h[g].ability].modifier;h[g].effects.push([a.abilities[h[g].ability].label,k[h[g].ability].modifier])}}var q=d.fetchRules(e,m);var h=a.affect(h,b.AFFECT_SKILLS,q,e,m)}d._fetch[e].skills[m]=h;return h},fetchPoints:function(j){if(j===undefined){j=a.max_level}var e={total:0,unused:build.skills.unused(),classes:[]};var g,h;for(var f=1;f<=j;f++){g=c.level[f].class_id;if(e.classes[g]===undefined){e.classes[g]={total:0,label:c.level[f].class_label}}h=build.skills.gain(f);e.classes[g].total+=h;e.total+=h}return e}}})();builder.tick("Build Summary: Abilities");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.abilities={cache:function(n){builder.log("sum","Caching Abilities ("+n+")");if(c.race.id==49){c.race={id:67,feats:[{id:354,label:"Low-light Vision",type:4,category:"racialability_ft_cat",slot:0},{id:240,label:"Keen Sense",type:4,category:"racialability_ft_cat",slot:1},{id:239,label:"Skill Affinity (Spot)",type:4,category:"racialability_ft_cat",slot:2},{id:238,label:"Skill Affinity (Search)",type:4,category:"racialability_ft_cat",slot:3},{id:237,label:"Skill Affinity (Listen)",type:4,category:"racialability_ft_cat",slot:4},{id:256,label:"Weapon Proficiency (Elf)",type:4,category:"proficiency_ft_cat",slot:5},{id:236,label:"Hardiness vs. Enchantments",type:4,category:"racialability_ft_cat",slot:6},{id:235,label:"Immunity To Sleep",type:4,category:"racialability_ft_cat",slot:7}],label:"Star Elf",icon:"ig_hu_selune",base_id:1,ecl:0,favored:1,ability:[0,0,-2,0,0,2]}}if(c.race.id==50){c.race={id:68,feats:[{id:354,label:"Low-light Vision",type:4,category:"racialability_ft_cat",slot:0},{id:240,label:"Keen Sense",type:4,category:"racialability_ft_cat",slot:1},{id:239,label:"Skill Affinity (Spot)",type:4,category:"racialability_ft_cat",slot:2},{id:238,label:"Skill Affinity (Search)",type:4,category:"racialability_ft_cat",slot:3},{id:237,label:"Skill Affinity (Listen)",type:4,category:"racialability_ft_cat",slot:4},{id:256,label:"Weapon Proficiency (Elf)",type:4,category:"proficiency_ft_cat",slot:5},{id:236,label:"Hardiness vs. Enchantments",type:4,category:"racialability_ft_cat",slot:6},{id:235,label:"Immunity To Sleep",type:4,category:"racialability_ft_cat",slot:7}],label:"Painted Elf",icon:"ira_we_raceicon",base_id:1,ecl:0,favored:3,ability:[0,2,0,-2,0,0]}}var f=a.max_level;var e=a.ability_selection;var m,g,l;for(var h=1;h<=f;h++){d._cache[h].abilities=[];m=d._cache[h].abilities;g=6;while(g--){m.push({value:0,rules:{any:[],normal:[],bonus:[],subselect:[],auto:[]}})}if(h==1){g=6;while(g--){m[g].value+=c.ability.id[g];m[g].value+=c.race.ability[g]}}else{var k=d._cache[h-1].abilities;g=6;while(g--){m[g].value+=k[g].value}if(e.find(h)){m[c.level[h].ability].value++}}g=6;while(g--){m[g].rules.any=d.fetchRules(h,b.FEAT_TYPE_ANY);m[g].rules.normal=d.fetchRules(h,b.FEAT_TYPE_NORMAL);m[g].rules.bonus=d.fetchRules(h,b.FEAT_TYPE_BONUS);m[g].rules.subselect=d.fetchRules(h,b.FEAT_TYPE_SUBSELECT);m[g].rules.auto=d.fetchRules(h,b.FEAT_TYPE_AUTO)}}},fetch:function(n,e){if(e===undefined){e=b.FEAT_TYPE_ANY}if(d._fetch[n].abilities[e]!==undefined){return d._fetch[n].abilities[e]}var g=d._cache[n].abilities;var f=[];var k,h=6,m;var l=[b.AFFECT_STR,b.AFFECT_DEX,b.AFFECT_CON,b.AFFECT_INT,b.AFFECT_WIS,b.AFFECT_CHA];if(c.ability.ROTE==undefined){c.ability.ROTE=[0,0,0,0,0,0]}while(h--){f[h]={value:0,modifier:0,effects:[]};f[h].value+=g[h].value;switch(e){case b.FEAT_TYPE_ANY:m=g[h].rules.any;break;case b.FEAT_TYPE_NORMAL:m=g[h].rules.normal;break;case b.FEAT_TYPE_BONUS:m=g[h].rules.bonus;break;case b.FEAT_TYPE_SUBSELECT:m=g[h].rules.subselect;break;case b.FEAT_TYPE_AUTO:m=g[h].rules.auto;break;default:m=[]}if(builder.game_version=="rote"&&n>1){f[h].value+=parseInt(c.ability.ROTE[h])}if((builder.game_version=="rote"||builder.game_version=="rotn")&&n>a.rot_epic_relevel){for(k=1;k<=4;k++){f[h].value+=parseInt(c.ability.ROT[k][h])}}f[h]=a.affect(f[h],l[h],m,n,e);f[h].modifier=Math.floor((f[h].value-10)/2)}d._fetch[n].abilities[e]=f;return f}}})();builder.tick("Build Summary: Caster Progression");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.caster={cache:function(h){builder.log("sum","Caching Caster Levels ("+h+")");var e=a.max_level;var g;for(var f=e;f>0;f--){d._cache[f].caster={rules:{any:[],normal:[],bonus:[],subselect:[],auto:[]}};g=d._cache[f].caster;g.rules.any=d.fetchRules(f,b.FEAT_TYPE_ANY);g.rules.normal=d.fetchRules(f,b.FEAT_TYPE_NORMAL);g.rules.bonus=d.fetchRules(f,b.FEAT_TYPE_BONUS);g.rules.subselect=d.fetchRules(f,b.FEAT_TYPE_SUBSELECT);g.rules.auto=d.fetchRules(f,b.FEAT_TYPE_AUTO)}},fetch:function(e,v){if(v===undefined){v=b.FEAT_TYPE_ANY}if(d._fetch[e].caster[v]!==undefined){return d._fetch[e].caster[v]}var f=d._cache[e].caster;var k=d.classes.fetch(a.max_level,v);var n=[];var r=[];var u,p,g,x,l,w,q;var t=a.max_level;for(u=1;u<=e;u++){p=c.level;w=b.CASTER_TYPE_NONE;switch(true){case (p.caster.arcane>0):w=b.CASTER_TYPE_ARCANE;break;case (p.caster.divine>0):w=b.CASTER_TYPE_DIVINE;break;case (p.caster.invoke>0):w=b.CASTER_TYPE_INVOKE;break}if(p.class_id==106){var m=[2,3,6,55,58];if([2,3,4,6,7,8,10].find(p.class_level)){var s=m.length;while(s--){if(n[m[s]]===undefined){if(k.classes[m[s]]!==undefined){n[m[s]]={id:m[s],label:k.classes[m[s]].label,icon:k.classes[m[s]].icon,level:0,type:b.CASTER_TYPE_DIVINE,value:0,multiclassed:0,effects:[[k.classes[m[s]].label,0]]}}else{continue}}n[m[s]].multiclassed=1;if(r[m[s]]===undefined){r[m[s]]=n[m[s]].effects.length;n[m[s]].effects.push([p.class_label,0])}n[m[s]].value+=1;n[m[s]].level++;l=r[m[s]];n[m[s]].effects[l][1]+=1}}continue}if(w==b.CASTER_TYPE_NONE){continue}g=p.caster.progress;if(p.prestige==1&&n[g]===undefined){continue}if(n[g]===undefined){n[g]={id:p.class_id,label:p.class_label,icon:p.class_icon,level:0,type:w,value:0,multiclassed:0,effects:[[p.class_label,0]]}}if(g!=p.class_id){n[g].multiclassed=1}if(p.prestige==1&&r[p.class_id]===undefined){r[p.class_id]=n[g].effects.length;n[g].effects.push([p.class_label,0])}x=0;if(p.caster.arcane>0){x=1}if(p.caster.divine>0){x=1}if(p.caster.invoke>0){x=1}if(x){n[g].value+=x;n[g].level++;l=(p.prestige==1)?r[p.class_id]:0;n[g].effects[l][1]+=x}}var h={arcane:{high:0,index:0,classes:[]},divine:{high:0,index:0,classes:[]},invoke:{high:0,index:0,classes:[]}};for(u in n){if(n.id===undefined){continue}switch(n.type){case b.CASTER_TYPE_ARCANE:h.arcane.classes[n.id]=n;if(n.value>h.arcane.high){h.arcane.high=n.value;h.arcane.index=n.id}break;case b.CASTER_TYPE_DIVINE:h.divine.classes[n[u].id]=n[u];if(n[u].value>h.divine.high){h.divine.high=n[u].value;h.divine.index=n[u].id}break;case b.CASTER_TYPE_INVOKE:h.invoke.classes[n[u].id]=n[u];if(n[u].value>h.invoke.high){h.invoke.high=n[u].value;h.invoke.index=n[u].id}break}}switch(v){case b.FEAT_TYPE_ANY:var o=f.rules.any;break;case b.FEAT_TYPE_NORMAL:var o=f.rules.normal;break;case b.FEAT_TYPE_BONUS:var o=f.rules.bonus;break;case b.FEAT_TYPE_SUBSELECT:var o=f.rules.subselect;break;case b.FEAT_TYPE_AUTO:var o=f.rules.auto;break;default:var o=[]}h=a.affect(h,b.AFFECT_CASTER_LEVEL,o,e,v);return a.runScripts(b.SCRIPT_SUMMARY_CASTER,h);d._fetch[e].caster[v]=h;return h}}})();builder.tick("Build Summary: Spells");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.spell={cache:function(f){builder.log("sum","Caching Spell Levels ("+f+")");var n=a.max_level;var o,e,k,m,h;var g=[];for(var l=n;l>0;l--){d._cache[l].spell={arcane:[],divine:[],invoke:[],rules:{any:[],normal:[],bonus:[],subselect:[],auto:[]}};e=c.level[l];o=d._cache[l].spell;h=e.class_id;if(g[h]!==undefined){continue}if(e.class_spellcaster==0){continue}g[h]=true;if(e.spell.arcane>0){o.arcane.push({class_id:h,class_label:e.class_label,level:e.spell.arcane})}if(e.spell.divine>0){o.divine.push({class_id:h,class_label:e.class_label,level:e.spell.divine})}if(e.spell.invoke>0){o.invoke.push({class_id:h,class_label:e.class_label,level:e.spell.invoke})}o.rules.any=d.fetchRules(l,b.FEAT_TYPE_ANY);o.rules.normal=d.fetchRules(l,b.FEAT_TYPE_NORMAL);o.rules.bonus=d.fetchRules(l,b.FEAT_TYPE_BONUS);o.rules.subselect=d.fetchRules(l,b.FEAT_TYPE_SUBSELECT);o.rules.auto=d.fetchRules(l,b.FEAT_TYPE_AUTO)}},fetch:function(e,m){if(m===undefined){m=b.FEAT_TYPE_ANY}if(d._fetch[e].spell[m]!==undefined){return d._fetch[e].spell[m]}var s=d._cache[e].spell;var q={arcane:{high:0,high_ability:0,classes:[],effects:[]},divine:{high:0,high_ability:0,classes:[],effects:[]},invoke:{high:0,high_ability:0,classes:[],effects:[]}};var r=a.max_level;var k,h,o,f;var g=[];var l,n;for(var j=e;j>0;j--){l=d.abilities.fetch(j);k=c.level[j].spell;h=c.level[j].class_id;if(g[h]!==undefined){continue}g[h]=true;if(k.arcane>0){o=k.arcane;f=k.arcane;n=(l[c.level[j].class_ability_spell].value-9);if(n<f){f=n}if(o>q.arcane.high){q.arcane.high=o;q.arcane.high_ability=f}q.arcane.classes[h]={class_id:h,class_label:c.level[j].class_label,level:o,level_ability:f}}if(k.divine>0){o=k.divine;f=k.divine;n=(l[c.level[j].class_ability_spell].value-9);if(n<f){f=n}if(o>q.divine.high){q.divine.high=o;q.divine.high_ability=f}q.divine.classes[h]={class_id:h,class_label:c.level[j].class_label,level:o,level_ability:f}}if(k.invoke>0){o=k.invoke;f=k.invoke;n=(l[c.level[j].class_ability_spell].value-9);if(n<f){f=n}if(o>q.invoke.high){q.invoke.high=o;q.invoke.high_ability=f}q.invoke.classes[h]={class_id:h,class_label:c.level[j].class_label,level:o,level_ability:f}}}switch(m){case b.FEAT_TYPE_ANY:var p=s.rules.any;break;case b.FEAT_TYPE_NORMAL:var p=s.rules.normal;break;case b.FEAT_TYPE_BONUS:var p=s.rules.bonus;break;case b.FEAT_TYPE_SUBSELECT:var p=s.rules.subselect;break;case b.FEAT_TYPE_AUTO:var p=s.rules.auto;break;default:var p=[]}q=a.affect(q,b.AFFECT_SPELL_LEVEL,p,e,m);d._fetch[e].spell[m]=q;return q}}})();builder.tick("Build Summary: Base Attack Bonus");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.bab={cache:function(f){builder.log("sum","Caching BAB ("+f+")");var n=a.max_level;var o,e,k,m,h;var g=[];for(var l=n;l>0;l--){d._cache[l].bab={classes:[],rules:{any:[],normal:[],bonus:[],subselect:[],auto:[]}};e=c.level[l];o=d._cache[l].bab;h=e.class_id;if(g[h]!==undefined){continue}g[h]=true;o.classes[h]={class_id:h,class_label:e.class_label,value:e.bab};o.rules.any=d.fetchRules(l,b.FEAT_TYPE_ANY);o.rules.normal=d.fetchRules(l,b.FEAT_TYPE_NORMAL);o.rules.bonus=d.fetchRules(l,b.FEAT_TYPE_BONUS);o.rules.subselect=d.fetchRules(l,b.FEAT_TYPE_SUBSELECT);o.rules.auto=d.fetchRules(l,b.FEAT_TYPE_AUTO)}},fetch:function(f,l){if(l===undefined){l=b.FEAT_TYPE_ANY}if(d._fetch[f].bab[l]!==undefined){return d._fetch[f].bab[l]}var p=d._cache[f].bab;var g={value:0,classes:[],effects:[]};var o=a.max_level;var e,j,m;var h=[];var k=f;while(k){e=c.level[k];j=e.class_id;if(h[j]!==undefined){k--;continue}h[j]=true;g.value+=e.bab;g.classes[j]={class_id:e.class_id,class_label:e.class_label,value:e.bab};g.effects.push([e.class_label,e.bab]);k--}switch(l){case b.FEAT_TYPE_ANY:var n=p.rules.any;break;case b.FEAT_TYPE_NORMAL:var n=p.rules.normal;break;case b.FEAT_TYPE_BONUS:var n=p.rules.bonus;break;case b.FEAT_TYPE_SUBSELECT:var n=p.rules.subselect;break;case b.FEAT_TYPE_AUTO:var n=p.rules.auto;break;default:var n=[]}g=a.affect(g,b.AFFECT_BAB,n,f,l);d._fetch[f].bab[l]=g;return g}}})();builder.tick("Build Summary: Classes");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.classes={fetch:function(n){if(n===undefined){n=a.max_level}var l={classes:[]};var k;var h=n;while(h>=1){k=c.level[h];if(l.classes[k.class_id]!==undefined){h--;continue}l.classes[k.class_id]={id:k.class_id,icon:k.class_icon,label:k.class_label,levels:builder.classLevel(h,k.class_id),skill:k.class_skill,hit_die:k.class_hit_die,ability_spell:k.class_ability_spell,ability_spell_dc:k.class_ability_spell_dc,prestige:k.prestige,spellcaster:k.class_spellcaster};h--}var g=[];h=l.classes.length;while(h--){if(l.classes[h]===undefined){continue}if(g[l.classes[h].levels]===undefined){g[l.classes[h].levels]=[]}g[l.classes[h].levels].push({id:l.classes[h].id,icon:l.classes[h].icon,label:l.classes[h].label,abbrev:d.abbreviate(l.classes[h].id),levels:l.classes[h].levels,prestige:l.classes[h].prestige})}var m=b.ID_NONE;l.order=[];var f=1,e;h=g.length;while(h--){if(g[h]===undefined){continue}e=g[h].length;while(e--){if(g[h][e].prestige==1){l.order[f]=g[h][e];f++}else{if(l.order[0]===undefined){l.order[0]=g[h][e]}else{l.order[f]=g[h][e];f++}}}}l.string=[];l.string_short=[];h=0;while(h<l.order.length){if(l.order[h]!==undefined){l.string.push(l.order[h].label+" ("+l.order[h].levels+")");l.string_short.push(l.order[h].abbrev+" ("+l.order[h].levels+")")}h++}l.string=l.string.join(", ");l.string_short=l.string_short.join(", ");return l},level:function(f,h){if(!f.length){return 0}if(h===undefined){h=a.max_level}var g=0;for(var e=1;e<=h;e++){if(f.find(c.level[e].class_id)){g++}}return g}}})();builder.tick("Build Summary: Hit Points");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.hp={fetch:function(e,m){if(e===undefined){e=a.max_level}if(m===undefined){m=b.FEAT_TYPE_ANY}var r={value:0,effects:[]};var p,l;var o=d.classes.fetch(e).classes;var k=o.length;while(k--){if(o[k]===undefined){continue}p=(o[k].hit_die*o[k].levels);r.value+=p;r.effects.push([o[k].label,p])}if(d.feats.have(a.featid_mind_over_body,e,m)){l=d.abilities.fetch(1);var h=[l[b.ABILITY_INT].modifier,l[b.ABILITY_CON].modifier].high();var n=l[b.ABILITY_CON].modifier;if(h>0){r.value+=h;r.effects.push([a.abilities[b.ABILITY_INT].label,h])}l=d.abilities.fetch(e);if(l[b.ABILITY_CON].modifier>0){p=(l[b.ABILITY_CON].modifier*e)-n;r.value+=p+h;r.effects.push([a.abilities[b.ABILITY_CON].label,p])}var j=d.feats.category("metamagic_ft_cat",e,m);var g=d.feats.category("spellcasting_ft_cat",e,m);var f=(j+g);if(f>0){r.value+=f;r.effects.push(["Mind Over Body",f])}}else{l=d.abilities.fetch(e);if(l[b.ABILITY_CON].modifier!=0){p=(l[b.ABILITY_CON].modifier*e);r.value+=p;r.effects.push([a.abilities[b.ABILITY_CON].label,p])}}var q=d.fetchRules(e,m);r=a.affect(r,b.AFFECT_HP,q,e,m);return r}}})();builder.tick("Build Summary: Armor");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.armor={fetch:function(m,e){if(m===undefined){m=a.max_level}if(e===undefined){e=b.FEAT_TYPE_ANY}var l={};l[b.ARMOR_TYPE_NATURAL]={value:10,effects:[["Base Armor",+10]],label:"Natural"};l[b.ARMOR_TYPE_AC]={value:0,effects:[],label:"Armor"};l[b.ARMOR_TYPE_DODGE]={value:0,effects:[],label:"Dodge"};l[b.ARMOR_TYPE_SHIELD]={value:0,effects:[],label:"Shield"};l[b.ARMOR_TYPE_DEFLECTION]={value:0,effects:[],label:"Deflection"};l[b.ARMOR_TYPE_DEXTERITY]={value:0,effects:[],label:"Dexterity"};var k=d.abilities.fetch(m,e);l[b.ARMOR_TYPE_DEXTERITY].value+=k[b.ABILITY_DEX].modifier;var j=d.fetchRules(m,e);l=a.affect(l,b.AFFECT_ARMOR,j,m,e);var f=d.skills.fetch(m);var g=f.length;for(i=0;i<g;i++){if(f.id==21){var h=Math.floor(f.value_raw/10);if(h>0){l[b.ARMOR_TYPE_AC].value+=h;l[b.ARMOR_TYPE_AC].effects.push(["Tumble",h])}break}}l.total=l[b.ARMOR_TYPE_NATURAL].value+l[b.ARMOR_TYPE_AC].value+l[b.ARMOR_TYPE_DODGE].value+l[b.ARMOR_TYPE_SHIELD].value+l[b.ARMOR_TYPE_DEFLECTION].value+l[b.ARMOR_TYPE_DEXTERITY].value;return l}}})();builder.tick("Build Summary: Attacks");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.attacks={fetch:function(f,p){if(f===undefined){f=a.max_level}if(p===undefined){p=b.FEAT_TYPE_ANY}var u=d.bab.fetch(f,p);var g={two_weapon:false,melee:{main_hand:{value:0,gain:[],scores:[],effects:[["Base Attack Bonus",u.value]],label:"Main Hand"},dual_main:{value:0,gain:[],scores:[],effects:[["Base Attack Bonus",u.value]],label:"Main Hand"},dual_off:{value:0,gain:[],scores:[],effects:[["Base Attack Bonus",u.value]],label:"Off Hand"},touch:{value:0,gain:[],scores:[],effects:[["Base Attack Bonus",u.value]],label:"Touch"}},ranged:{main_hand:{value:0,gain:[],scores:[],effects:[["Base Attack Bonus",u.value]],label:"Main Hand"},touch:{value:0,gain:[],scores:[],effects:[["Base Attack Bonus",u.value]],label:"Touch"}}};var h=d.feats.have(a.featid_weapon_finesse,f,p);var r=d.feats.have(a.featid_zen_archery,f,p);var m=d.feats.have(a.featid_intuitive_attack,f,p);var o=d.abilities.fetch(f,p);var s=b.ABILITY_STR;var v=b.ABILITY_DEX;var n,q;var k=true;var e=true;if(h==true&&o[b.ABILITY_DEX].modifier>=o[b.ABILITY_STR].modifier){s=b.ABILITY_DEX}if(m==true&&o[b.ABILITY_WIS].modifier>=o[b.ABILITY_STR].modifier){s=b.ABILITY_WIS}if(r==true&&o[b.ABILITY_WIS].modifier>=o[b.ABILITY_DEX].modifier){v=b.ABILITY_WIS}if(o[s].modifier!=0){n=o[s].modifier;q=a.abilities[s].label;g.melee.touch.value+=n;g.melee.touch.effects.push([q,n]);g.melee.main_hand.value+=n;g.melee.main_hand.effects.push([q,n]);g.melee.dual_main.value+=n;g.melee.dual_main.effects.push([q,n]);g.melee.dual_off.value+=n;g.melee.dual_off.effects.push([q,n])}if(o[v].modifier!=0){n=o[v].modifier;q=a.abilities[v].label;g.ranged.touch.value+=n;g.ranged.touch.effects.push([q,n]);g.ranged.main_hand.value+=n;g.ranged.main_hand.effects.push([q,n])}g.melee.dual_main.value+=-6;g.melee.dual_main.effects.push(["Dual Wielding",-6]);g.melee.dual_off.value+=-10;g.melee.dual_off.effects.push(["Dual Wielding",-10]);g.two_weapon=d.feats.have(a.featid_2wf,f,p);if(!g.two_weapon){if(builder.classLevel(f,7)>=2){g.two_weapon=d.feats.have(a.featid_2wf_ranger,f,p)}}if(e==true){g.melee.dual_main.value+=+2;g.melee.dual_main.effects.push(["Light Off Hand Weapon",+2]);g.melee.dual_off.value+=+2;g.melee.dual_off.effects.push(["Light Off Hand Weapon",+2])}var t=d.fetchRules(f,p);g=a.affect(g,b.AFFECT_ATTACK,t,f,p);g.melee.main_hand.total=Math.ceil(u.value/5);g.melee.dual_main.total=Math.ceil(u.value/5);g.melee.dual_off.total=1+g.melee.dual_off.gain.length;g.ranged.main_hand.total=Math.ceil(u.value/5);g.melee.touch.total=1;g.melee.touch.scores=[u.value+g.melee.touch.value];g.ranged.touch.total=1;g.ranged.touch.scores=[u.value+g.ranged.touch.value];var j=(0+u.value);while(j>0){g.melee.main_hand.scores.push(j+g.melee.main_hand.value);g.ranged.main_hand.scores.push(j+g.ranged.main_hand.value);g.melee.dual_main.scores.push(j+g.melee.dual_main.value);if(g.melee.dual_off.scores.length==0){g.melee.dual_off.scores.push(j+g.melee.dual_off.value)}j-=5}var l;l=g.melee.main_hand.gain.length;while(l--){g.melee.main_hand.scores.push(u.value+g.melee.main_hand.gain[l]+g.melee.main_hand.value)}l=g.melee.dual_main.gain.length;while(l--){g.melee.dual_main.scores.push(u.value+g.melee.dual_main.gain[l]+g.melee.dual_main.value)}l=g.melee.dual_off.gain.length;while(l--){g.melee.dual_off.scores.push(u.value+g.melee.dual_off.gain[l]+g.melee.dual_off.value)}l=g.ranged.main_hand.gain.length;while(l--){g.ranged.main_hand.scores.push(u.value+g.ranged.main_hand.gain[l]+g.ranged.main_hand.value)}if(!g.melee.main_hand.scores.length){g.melee.main_hand.scores=[0]}if(!g.melee.dual_main.scores.length){g.melee.dual_main.scores=[0]}if(!g.melee.dual_off.scores.length){g.melee.dual_off.scores=[0]}if(!g.ranged.main_hand.scores.length){g.ranged.main_hand.scores=[0]}g.melee.main_hand.string=("+"+g.melee.main_hand.scores.join(" / +")).replace("+-","-");g.melee.dual_main.string=("+"+g.melee.dual_main.scores.join(" / +")).replace("+-","-");g.melee.dual_off.string=("+"+g.melee.dual_off.scores.join(" / +")).replace("+-","-");g.ranged.main_hand.string=("+"+g.ranged.main_hand.scores.join(" / +")).replace("+-","-");return a.runScripts(b.SCRIPT_SUMMARY_ATTACK,g)}}})();builder.tick("Build Summary: Damage Reductions");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.reduction={fetch:function(g,e){if(g===undefined){g=a.max_level}if(e===undefined){e=b.FEAT_TYPE_ANY}var f=d.fetchRules(g,e);return a.affect({},b.AFFECT_REDUCTION,f,g,e)}}})();builder.tick("Build Summary: Resistances");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.resistance={fetch:function(g,e){if(g===undefined){g=a.max_level}if(e===undefined){e=b.FEAT_TYPE_ANY}var f=d.fetchRules(g,e);return a.affect({},b.AFFECT_RESISTANCE,f,g,e)}}})();builder.tick("Build Summary: Spell DC");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.spell_dc={fetch:function(e,m){if(e===undefined){e=a.max_level}if(m===undefined){m=b.FEAT_TYPE_ANY}var t=[];var l=d.abilities.fetch(e,m);var o=d.caster.fetch(e,m);var n=(o.arcane.high>o.divine.high)?o.arcane.high:o.divine.high;if(o.invoke.high>n){n=o.invoke.high}var u=d.caster.fetch(e,m);var s=d.fetchRules(e,m);var h,r,f,p,g;var q=d.classes.fetch(e,m);var k=q.classes.length;while(k--){if(q.classes[k]===undefined){continue}g=q.classes[k].id;if(q.classes[k].spellcaster==0){continue}t[g]={id:g,label:q.classes[k].label,base:0,effects:[],schools:[]};t[g].base+=10;t[g].effects.push(["Base DC",10]);r=l[q.classes[k].ability_spell_dc].modifier;t[g].base+=r;t[g].effects.push([a.abilities[q.classes[k].ability_spell_dc].label,r]);p=0;if(u.arcane.classes[g]!==undefined){p=Math.floor((u.arcane.classes[g].value-20)/3)}if(u.divine.classes[g]!==undefined){p=Math.floor((u.divine.classes[g].value-20)/3)}if(u.invoke.classes[g]!==undefined){p=Math.floor((u.invoke.classes[g].value-20)/3)}if(p>0){t[q.classes[k].id].base+=p;t[q.classes[k].id].effects.push(["Epic Caster",p])}t[g]=a.affect(t[g],b.AFFECT_SPELL_DC_BASE,s,e,m);h=10;while(h--){t[g].schools[h]={value:0+t[g].base,effects:[]}}if(g==10){if(c.school.id!=b.ID_NONE&&c.school.id!=b.SCHOOL_GENERAL){t[g].schools[c.school.id].value+=+1;t[g].schools[c.school.id].effects.push(["Wizard Specialization",+1])}}t[g].schools=a.affect(t[g].schools,b.AFFECT_SPELL_DC,s,e,m);t[g].high=0;h=10;while(h--){if(t[g].schools[h].value>t[g].high){t[g].high=t[g].schools[h].value}}t[g].schools[0]={value:t[g].base,effects:t[g].effects}}return t}}})();builder.tick("Build Summary: XP Penalty");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.xp_penalty={fetch:function(m){var f={value:0,effects:[]};var h=d.classes.fetch(m);var e=[];var l=0;var g=-1;var j=h.classes.length;while(j-->=0){if(h.classes[j]===undefined){continue}if(h.classes[j].prestige==1){continue}if(j==c.race.favored){continue}e.push({id:j,levels:h.classes[j].levels,label:h.classes[j].label});if(h.classes[j].levels>l){l=h.classes[j].levels;g=e.length-1}}if(c.race.favored==b.ID_NONE){e.splice(g,1);if(e.length==0){return f}l=0;g=-1;j=0;while(j<e.length){if(e[j].levels>l){l=e[j].levels;g=j;break}j++}}if(e.length==0){return f}var k=e[g].levels;e.splice(g,1);if(e.length==0){return f}j=0;while(j<e.length){if(k-e[j].levels>1){f.value+=-20;f.effects.push([e[j].label,"-20%"])}j++}return f}}})();builder.tick("Build Summary: Sneak Attack");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.summary.sneak_attack={fetch:function(g,e){if(g===undefined){g=a.max_level}if(e===undefined){e=b.FEAT_TYPE_ANY}var f=d.fetchRules(g,e);return a.affect({value:0,value_prestige:0,effects:[]},b.AFFECT_SNEAK_ATTACK,f,g,e)}}})();builder.tick("Builder Menus");(function(){var a=function(){};a.prototype.initialised=[];a.prototype.store=[];a.prototype.initialise=function(c,b){if(this.store[b]===undefined){return false}this.store[b].render(c);this.initialised[b]=true;return true};a.prototype.show=function(c,b,d){this.hide();if(this.initialised[b]===undefined){if(!this.initialise(c,b)){return false}}this.store[b].show(c,d);setTimeout(function(){$("body").bind("click",function(e){if(!$(e.target).parents(".builder_menu").length){builder.menu.hide()}})},100)};a.prototype.hide=function(){var c=builder.menu.store.length;for(var b=0;b<c;b++){builder.menu.store[b].hide()}$("body").unbind("click")};builder.menu=new a()})();builder.tick("Builder Menus");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.menu.store[b.MENU_TYPE_FEATS]={render:function(e){$("#menu_feats").remove();$("body").append('<div class="builder_menu" id="menu_feats"><ul><li class="option"><a id="option_feats_clear_all" onclick="builder.menu.store['+b.MENU_TYPE_FEATS+'].trigger(1);return false;"></a><span>Clear <strong>All</strong> Feats</span></li><li class="option"><a id="option_feats_clear_normal" onclick="builder.menu.store['+b.MENU_TYPE_FEATS+'].trigger(2);return false;"></a><span>Clear <strong>Normal</strong> Feats</span></li><li class="option"><a id="option_feats_clear_bonus" onclick="builder.menu.store['+b.MENU_TYPE_FEATS+'].trigger(3);return false;"></a><span>Clear <strong>Bonus</strong> Feats</span></li></ul></div>');$("#menu_feats").css("left",$(e.target)[0].offsetLeft).css("top",$(e.target)[0].offsetTop+$(e.target)[0].offsetHeight)},trigger:function(e){builder.menu.hide();builder.processing("Updating Build",function(h){if(e==1||e==2){var f=a.max_level;for(var g=1;g<=f;g++){c.feats.normal[g]={}}}if(e==1||e==3){c.feats.bonus={};c.feats.subselect={};c.feats.qtm={};c.feats.rcs={}}build.changed()},{})},show:function(e,g){var f=$(e.target).offset();$("#menu_feats").css({left:f.left,top:f.top+16}).show()},hide:function(){$("#menu_feats").hide()}}})();builder.tick("Builder Menus");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.menu.store[b.MENU_TYPE_CLASS]={level:1,render:function(h){var j=[];var l=[];var g=(new dataTable()).table("classes");var f=g.data.length;var k;while(f--){k=g.row(false,f);if(k.field("playerclass")!=1){continue}if(k.field("prereqtable",b.ID_NONE)!=b.ID_NONE){l.push({id:k.field("a_id"),label:k.field("name")})}else{j.push({id:k.field("a_id"),label:k.field("name")})}}j.sort(function(n,m){var p=n.label.toLowerCase();var o=m.label.toLowerCase();if(p<o){return -1}if(p>o){return 1}return 0});l.sort(function(n,m){var p=n.label.toLowerCase();var o=m.label.toLowerCase();if(p<o){return -1}if(p>o){return 1}return 0});for(f=0;f<j.length;f++){j[f]='<option value="'+j[f].id+'">'+j[f].label+"</option>"}for(f=0;f<l.length;f++){l[f]='<option value="'+l[f].id+'">'+l[f].label+"</option>"}var e='<optgroup label="Base Classes">'+j.join("")+'</optgroup><optgroup label="Prestige Classes">'+l.join("")+"</optgroup>";$("#menu_class").remove();$("body").append('<div class="builder_menu" id="menu_class"><ul><li class="option"><a id="levelMenu_Fill" class="menuListGo" onclick="builder.menu.store['+b.MENU_TYPE_CLASS+'].trigger(1);return false;"></a><span>Fill all remaining levels with <em></em></span></li><li class="option"><a id="levelMenu_CloneOver" class="menuListGo" onclick="builder.menu.store['+b.MENU_TYPE_CLASS+'].trigger(2);return false;"></a><span>Change the next <input type="text" id="replace_over" value="9" size="2"> levels to <em></em> by <strong>overwritting</strong></span></li><li class="option"><a id="levelMenu_ClonePush" class="menuListGo" onclick="builder.menu.store['+b.MENU_TYPE_CLASS+'].trigger(3);return false;"></a><span>Change the next <input type="text" id="replace_push" value="9" size="2"> levels to <em></em> by <strong>pushing</strong></span></li><li class="option"><a id="levelMenu_Delete" class="menuListGo" onclick="builder.menu.store['+b.MENU_TYPE_CLASS+'].trigger(4);return false;"></a><span>Delete this row and move all remaining rows up</span></li><li class="option"><a id="levelMenu_Insert" class="menuListGo" onclick="builder.menu.store['+b.MENU_TYPE_CLASS+'].trigger(5);return false;"></a><span>Insert <input type="text" id="class_insert_rows" value="1" size="2"> rows of <select id="class_insert">'+e+'</select></span></li><li class="option"><a id="levelMenu_Replace" class="menuListGo" onclick="builder.menu.store['+b.MENU_TYPE_CLASS+'].trigger(6);return false;"></a><span>Replace all levels of <em></em> with <select id="class_replace">'+e+"</select></span></li></ul></div>")},trigger:function(e){builder.menu.hide();builder.processing("Updating Build",function(j){switch(j.index){case 1:var l=c.level[j.level].class_id;build.classes.level=(j.level+1);build.classes.change(l,(a.max_level-j.level));break;case 2:var l=c.level[j.level].class_id;var n=parseInt($("#replace_over").val());build.classes.level=j.level+1;build.classes.change(l,n);break;case 3:var l=c.level[j.level].class_id;var n=parseInt($("#replace_push").val());var m=a.max_level;while(m>j.level&&(m-n)>=1){build.classes.level=m;build.classes.change(c.level[(m-n)].class_id,1,true);m--}build.classes.level=j.level+1;build.classes.change(l,n);break;case 4:var f=j.level;var o=a.max_level;for(var m=f;m<o;m++){build.classes.level=m;build.classes.change(c.level[m+1].class_id,1,true)}build.classes.level=o;build.classes.change(c.level[o-1].class_id,true);build.changed(f);break;case 5:var o=a.max_level;build.classes.history=[];for(var m=1;m<=o;m++){build.classes.history[m]=c.level[m].class_id}var l=parseInt($("#class_insert").val());var n=parseInt($("#class_insert_rows").val());var f=j.level;var k=a.max_level-n;var h=[];for(var m=f;m<=k;m++){h[m]=c.level[m].class_id}for(var m=f;m<=k;m++){build.classes.level=(m+n);build.classes.change(h[m],1,true)}builder.history.ignore=true;build.classes.level=j.level;build.classes.change(l,n);builder.history.ignore=false;builder.history.add(b.HISTORY_SCOPE_CLASS_BATCH);break;case 6:var o=a.max_level;build.classes.history=[];for(var m=1;m<=o;m++){build.classes.history[m]=c.level[m].class_id}var g=c.level[j.level].class_id;var l=parseInt($("#class_replace").val());builder.history.ignore=true;var o=a.max_level;for(var m=1;m<=o;m++){if(c.level[m].class_id==g){build.classes.level=m;build.classes.change(l,1,true)}}build.classes.level=j.level;build.classes.change(l,n);builder.history.ignore=false;builder.history.add(b.HISTORY_SCOPE_CLASS_BATCH);build.changed(1);break}},{index:e,level:this.level})},show:function(g,f){this.level=f;var k=c.level[f].class_id;var j=(new dataTable()).table("classes").row(k).field("name");$("#menu_class em").html("<strong>"+j+"</strong>");var h=($("#build")[0].offsetLeft+$(g.target)[0].offsetLeft);var m=$(g.target).parents("td")[0].offsetTop+$("#build")[0].offsetTop;m+=($(g.target)[0].offsetTop+$(g.target)[0].offsetHeight);var n=$("body")[0].clientHeight;var l=$("#output_utilities")[0].offsetHeight;var o=$("#menu_class").height();var e=(m+o);if(e>(n-l)){m-=(o+20)}$("#menu_class").css("left",h).css("top",m).show()},hide:function(){$("#menu_class").hide()}}})();builder.tick("Builder Menus");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.menu.store[builder.constant.MENU_TYPE_SKILLS]={index:0,render:function(e){$("#menu_skills").remove();$("body").append('<div class="builder_menu" id="menu_skills"><ul><li class="option"><a id="option_skills_delete" onclick="builder.menu.store['+b.MENU_TYPE_SKILLS+'].trigger(1);return false;"></a><span>Delete <strong>Skill</strong></span></li><li class="option"><a id="option_skills_clear" onclick="builder.menu.store['+b.MENU_TYPE_SKILLS+'].trigger(2);return false;"></a><span>Clear All <strong>Skill</strong> Points</span></li><li class="option"><a id="option_skills_max" onclick="builder.menu.store['+b.MENU_TYPE_SKILLS+'].trigger(3);return false;"></a><span>Max on all levels</span></li><li class="option"><a id="option_skills_max_single" onclick="builder.menu.store['+b.MENU_TYPE_SKILLS+'].trigger(4);return false;"></a><span>Max on all <em>Single Point</em> levels</span></li></ul></div>')},trigger:function(g){builder.menu.hide();var f=a.max_level;var e=builder.menu.store[b.MENU_TYPE_SKILLS].index;builder.processing("Updating Build",function(h){switch(g){case 1:build.skills.decreaseMax(e,1,true);c.skills.splice(e,1);break;case 2:build.skills.decreaseMax(e,1,true);break;case 3:build.skills.decreaseMax(e,1,true);build.skills.increaseMax(e,f,false,true);break;case 4:build.skills.decreaseMax(e,1,true);build.skills.increaseMax(e,f,true,true);break}build.changed()},{})},show:function(f,j){var g=$(f.target).get(0);if($(g).hasClass("icon_menu")){g=$(g).parent()}var h=$(g).offset();var e=$(g).attr("data-index");builder.menu.store[b.MENU_TYPE_SKILLS].index=e;$("#menu_skills strong").html(c.skills[e].label);$("#menu_skills").css("left",h.left).css("top",h.top+$(g).height());$("#menu_skills").show()},hide:function(){$("#menu_skills").hide()}}})();builder.tick("Output Generators");builder.output.template.build_table=function(){var f=builder.constant;var a=builder.rules;$("#output_build").empty().append('<div id="build"><table id="table_build"><thead><tr><th class="class">Class</th><th class="ability">STR</th><th class="ability">DEX</th><th class="ability">CON</th><th class="ability">INT</th><th class="ability">WIS</th><th class="ability">CHA</th><th class="bab">BAB</th><th class="saves" colspan="3">Saves</th><th class="feats"><a class="menu_dropdown" onclick="builder.menu.show(event,'+f.MENU_TYPE_FEATS+');"></a>Feats</th><th class="extra">Extra</th></tr></thead><tbody></tbody></table></div>');var h=(builder.game_version=="rote"||builder.game_version=="rotn"),c=(builder.game_version=="rote"),e,d,b=a.max_level,g=false;for(e=1;e<=b;e++){g=(e==b)?" last":"";$("#output_build tbody").append('<tr id="level_'+e+'" class="class1'+g+'"><td class="class_select"><a class="class" data-index="'+e+'" id="class_'+e+'" onclick="build.classes.openSelector(event,'+e+');"></a><div id="options_'+e+'"></div></td><td class="ability" id="str_'+e+'" title="Strength"></td><td class="ability" id="dex_'+e+'" title="Dexterity"></td><td class="ability" id="con_'+e+'" title="Constitution"></td><td class="ability" id="int_'+e+'" title="Intelligence"></td><td class="ability" id="wis_'+e+'" title="Wisdom"></td><td class="ability" id="cha_'+e+'" title="Charisma"></td><td class="saves" id="bab_'+e+'" title="BAB"></td><td class="saves" id="fort_'+e+'" title="Fortitude"></td><td class="saves" id="refl_'+e+'" title="Reflex"></td><td class="saves" id="will_'+e+'" title="Will"></td><td class="feats" id="feats_'+e+'"></td><td class="extra" id="extra_'+e+'"></td></tr>');if(c&&e==1){$("#output_build tbody").append('<tr id="rote_extra_ability" class="class1'+g+'"><td class="class_select"><span class="epic-relevel-frame" style="color:#a5a5a5;display:inline-block;padding:5px 0 5px 50px;font-size:1.1em;">Easy Mode Bonus</span></td><td id="rote_extra_ability_str" class="ability"><a class="select" onclick="builder.ui.clickROTExtraAbility(event,0);" title="Strength"></a></td><td id="rote_extra_ability_dex" class="ability"><a class="select" onclick="builder.ui.clickROTExtraAbility(event,1);" title="Dexterity"></a></td><td id="rote_extra_ability_con" class="ability"><a class="select" onclick="builder.ui.clickROTExtraAbility(event,2);" title="Constitution"></a></td><td id="rote_extra_ability_int" class="ability"><a class="select" onclick="builder.ui.clickROTExtraAbility(event,3);" title="Intelligence"></a></td><td id="rote_extra_ability_wis" class="ability"><a class="select" onclick="builder.ui.clickROTExtraAbility(event,4);" title="Wisdom"></a></td><td id="rote_extra_ability_cha" class="ability"><a class="select" onclick="builder.ui.clickROTExtraAbility(event,5);" title="Charisma"></a></td><td id="rote_extra_ability_points" colspan="7" class="extra" style="padding: 8px 0 7px 25px;color:#a5a5a5;"><strong>5</strong> &nbsp;Ability Points Remaining</td></tr>')}if(h&&e==a.rot_epic_relevel){for(d=1;d<=4;d++){$("#output_build tbody").append('<tr id="relevel_'+d+'" class="class1'+g+'"><td class="class_select"><span class="epic-relevel-frame" style="color:#a5a5a5;display:inline-block;padding:5px 0 5px 50px;font-size:1.1em;">Epic Relevel '+d+'</span></td><td id="epic_relevel_'+d+'_str" class="ability"><a class="select" onclick="builder.ui.clickEpicRelevel(event,'+d+',0);" title="Strength"></a></td><td id="epic_relevel_'+d+'_dex" class="ability"><a class="select" onclick="builder.ui.clickEpicRelevel(event,'+d+',1);" title="Dexterity"></a></td><td id="epic_relevel_'+d+'_con" class="ability"><a class="select" onclick="builder.ui.clickEpicRelevel(event,'+d+',2);" title="Constitution"></a></td><td id="epic_relevel_'+d+'_int" class="ability"><a class="select" onclick="builder.ui.clickEpicRelevel(event,'+d+',3);" title="Intelligence"></a></td><td id="epic_relevel_'+d+'_wis" class="ability"><a class="select" onclick="builder.ui.clickEpicRelevel(event,'+d+',4);" title="Wisdom"></a></td><td id="epic_relevel_'+d+'_cha" class="ability"><a class="select" onclick="builder.ui.clickEpicRelevel(event,'+d+',5);" title="Charisma"></a></td><td id="epic_relevel_'+d+'_points" colspan="7" class="extra" style="padding: 8px 0 7px 25px;color:#a5a5a5;" id="extra_'+e+"_relevel_"+d+'"><strong>5</strong> &nbsp;Ability Points Remaining</td></tr>')}}if(g){$("#output_build tbody").append('<tr class="level_spacer"><td colspan="17">&nbsp;</td></tr>')}}};builder.tick("Output Generators");builder.output.template.skills_table=function(){var a=builder.rules;$("#table_skills").remove();$("#build").prepend('<table id="table_skills" class="unselectable hidden"><thead><tr><th class="class">Class</th><th class="skill_col">Gain</th><th class="skill_col">Saved</th><th class="skill_col">Unused</th><th style="text-align:left;">Skills</th></tr></thead><tbody></tbody></table>');$("#table_skills tbody").append('<tr class="class1"><td class="unselectable contentRight"><a class="sort_skills" onclick="build.skills.sort();">Sort Skills Alphabetically</a></td><td class="unselectable skill_col">&nbsp;</td><td class="unselectable skill_col">&nbsp;</td><td id="skill_total" class="unselectable skill_col">0</td><td id="skill_expand"></td></tr>');var c=false;for(var b=1;b<=a.max_level;b++){c=(b==a.max_level)?" last":"";$("#table_skills tbody").append('<tr id="skill_level_'+b+'" class="class1'+c+'"><td><a class="unselectable class"></a></td><td id="skill_gain_'+b+'" class="unselectable skill_col">0</td><td id="skill_saved_'+b+'" class="unselectable skill_col">0</td><td id="skill_total_'+b+'" class="unselectable skill_col">0</td><td class="unselectable skill_values" id="skill_values_'+b+'">&nbsp;</td></tr>');if(c){$("#table_skills tbody").append('<tr class="level_spacer"><td colspan="5">&nbsp;</td></tr>')}}};builder.tick("Output Generators");builder.output.template.stats_frame=function(){var a=builder.constant;$("#output_stats").empty().append('<a class="block race" onclick="builder.selector.generic.open('+a.SELECTOR_RACE+');"><span class="icon"></span><span class="label"></span></a><a class="block alignment" onclick="builder.selector.generic.open('+a.SELECTOR_ALIGNMENT+');"><span class="icon"></span><span class="label"></span></a><a class="block deity" onclick="builder.selector.generic.open('+a.SELECTOR_DEITY+');"><span class="icon"></span><span class="label"></span></a><a class="block background" onclick="builder.selector.generic.open('+a.SELECTOR_BACKGROUND+');"><span class="icon"></span><span class="label"></span></a>')};builder.tick("Output Generators");builder.output.template.abilities_table=function(){var a=builder.rules;$("#output_abilities").empty();var b=a.abilities;var d="";var e=b.length;for(var c=0;c<e;c++){d+="<tr><td>"+b[c].label+'</td><td class="base" id="ability_'+b[c].id+'"></td><td id="final_'+b[c].id+'"></td><td id="mod_'+b[c].id+'"></td></tr>'}$("#output_abilities").append('<table id="abilities"><thead><tr><th>Ability</th><th>Base</th><th>Final</th><th>Mod</th></tr></thead><tfoot><tr><td colspan="4"><a onclick="builder.selector.abilities.show();">Change Base Abilities</a></td></tr></tfoot><tbody id="attrBody">'+d+"</tbody></table>")};builder.tick("Build Utilities");builder.output.template.utilities_bar=function(){var a=builder.constant;$("#output_utilities").empty().append('<div id="utilFade"></div><div class="floatLeft ignorePanelClick"><div class="button build_info" onclick="build.info.show();"><div class="hover">Change <strong>Build Information</strong></div><span>Build Info</span></div><div class="button summary" onclick="builder.summary.output.update();"><div class="hover">View the <strong>Build Summary</strong></div><span>Summary</span></div><div class="button save disabled" onclick="build.info.saveBuild();"><div class="hover">Nothing to Save</div><span>Save</span></div><div class="button undo" onclick="builder.history.undo();"><div class="hover">Nothing to Undo</div><span>Undo</span></div><div class="button redo" onclick="builder.history.redo();"><div class="hover">Nothing to Redo</div><span>Redo</span></div></div><div class="floatRight"><div class="button toggle on build" onclick="builder.changeScope('+a.SCOPE_BUILD+');"><div class="hover">Switch to <strong>Edit Build</strong> Mode</div><span>Build</span></div><div class="button toggle skills" onclick="builder.changeScope('+a.SCOPE_SKILLS+');"><div class="hover">Switch to <strong>Edit Skills</strong> Mode</div><span>Skills</span></div><div class="button options" onclick="sliph.showBuilderOptions();"><div class="hover">Builder <strong>Options</strong></div><span>Options</span></div><div class="button exit" onclick="build.info.exitBuilder();"><div class="hover"><strong>Exit</strong></div><span>Exit</span></div></div><div class="clearBoth"></div>')};builder.tick("Build Information");builder.output.template.build_info=function(){$("div.selector.info").remove();$("body").append('<div class="selector info"><div class="dialog"><div class="header"><span>Build Information</span><div class="close" onclick="build.info.close();"></div></div><div class="inner"><div class="name"><div class="invalid"><div></div>Please provide a build name.</div><span>Build Name</span><input type="text" name="build_name" id="build_name" value=""></div><div class="tabs"><div class="tab selected">Description</div><div class="tab">Pros</div><div class="tab">Cons</div><div class="tab">Notes</div><div class="tab">Tags</div><div class="clear"></div></div><div id="tab_desc" class="tab_content"><div class="tab_info">Provide a brief description of the build.</div><textarea rows="10" cols="25"></textarea></div><div id="tab_note" class="hidden tab_content"><div class="tab_info">Here you can provide any additional notes or comments about the build.</div><textarea rows="10" cols="25"></textarea></div><div id="tab_pros" class="hidden tab_content"><div class="tab_info">List any highlights of the build. Separate multiple points on a new line.</div><textarea rows="10" cols="25"></textarea></div> <div id="tab_cons" class="hidden tab_content"><div class="tab_info">List any downsides of the build. Separate multiple points on a new line.</div><textarea rows="10" cols="25"></textarea></div><div id="tab_tags" class="hidden tab_content"><div class="tab_info">Select up to 10 existing or new tags which apply to this build.</div><div class="tags_existing"><div class="clearBoth">&nbsp;</div></div><div class="tags_new"><p><strong>Create new tags:</strong><br><span>- Separate multiple tags with a new line.<br>- All tags you create will be available to all members.<br>- New tags will take priority when enforcing the 10 tag limit.<br>- <strong>Do not use sentences</strong>, use 1 to 3 keywords only.</span></p><textarea name="new_tags" id="new_tags" rows="8" cols="20"></textarea></div><div class="clearBoth"></div></div><div class="footer"><p>Changes will not be saved unless you click the <strong>Apply</strong> button.</p><a class="button" onclick="build.info.apply();">Apply</a><a class="button" onclick="build.info.close();">Cancel</a></div></div><div class="swirl_bl"></div><div class="swirl_br"></div></div></div>');build.info.initialise()};builder.tick("Module: Classes");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.classes={level:1,history:[],openSelector:function(f,e){if($(f.target).attr("data-dragging")!==undefined){return}if($(f.target).hasClass("level_no")){return false}builder.selector.generic.open(b.SELECTOR_CLASS,e)},validate:function(J,X,l,m){if(m===undefined){m=false}var s=new buildValidator();if(!X){X=(new dataTable()).table("classes").row(J)}var z={};var H=[];var P=0;var B=X.field("a_id");for(var V=1;V<=l;V++){if(z[c.level[l].class_id]!==undefined){continue}z[c.level[l].class_id]=true;H.push(c.level[l].class_id);P++}if(P>a.max_classes){for(var V=0;V<H.length;V++){if(V>=a.max_classes){s.error("Class Restrictions","Too many classes ("+a.max_classes+" maximum)");break}if(H[V]==B){break}}}if(m==true){var x=X.field("prereqtable");if(x!=b.ID_NONE){var p=(new dataTable()).table(x);var P=p.data.length,r;var W,h,K,S;var G=(new dataTable()).table("skills");var g=(l-1);if(g<1){g=1}var q=d.skills.fetch(g);for(var V=0;V<P;V++){r=p.row(false,V);if(r.field("reqtype")=="skill"){W=r.field("reqparam1",b.ID_NONE);h=r.field("reqparam2",b.ID_NONE);if(W>=b.ID_NONE){K=0;S=q.length;while(S--){if(q[S].id==W){K=q[S].value_raw;break}}if(h!=b.ID_NONE&&K<h){s.warning("Skill Requirements",G.row(W).field("name")+" "+h)}}}}}}else{var x=X.field("prereqtable");if(l==1&&x!=-1){s.error("Class Restrictions","Cannot start with a <em>Prestige Class</em>")}var ab=X.field("maxlevel");if(ab>0&&builder.classLevel((l-1),X.field("a_id"))>=ab){s.error("Class Restrictions","Maximum level reached ("+ab+" maximum)")}var R=X.field("alignrestrict",0);var T=X.field("alignrstrcttype",0);var u=X.field("invertrestrict",0);if(build.alignment.restricted(R,T,u)){if(l==1){s.error("Class Restrictions","Invalid Alignment")}else{s.warning("Class Restrictions","Requires alignment shift")}}if(x!=b.ID_NONE){var p=(new dataTable()).table(x);var P=p.data.length;var r;var Z=false;var D=false;var U=false;var y=false;var C=false;var f=false;var A=false;var e=false;var W,h,K,S,aa;var k,t,O;var F=[];var I=[];var o=[];var w=[];var M=[];var Y=[];var E=(new dataTable()).table("feat");var n=(new dataTable()).table("racialtypes");var Q=(new dataTable()).table("racialsubtypes");var v=(new dataTable()).table("classes");var G=(new dataTable()).table("skills");var g=(l-1);if(g<1){g=1}var L=d.bab.fetch(g);var ac=d.spell.fetch(g);var q=d.skills.fetch(g);var N=d.sneak_attack.fetch(g);for(var V=0;V<P;V++){r=p.row(false,V);switch(r.field("reqtype")){case"sad":aa=r.field("reqparam1",b.ID_NONE);if(aa!=b.ID_NONE&&N.value_prestige<aa){s.error("Special","Sneak Attack Dice "+aa+"d6")}break;case"feat":k=r.field("reqparam1");if(!d.feats.have(k,l)){F.push(E.row(k).field("feat"));break}break;case"feator":if(Z&&D){continue}Z=true;k=r.field("reqparam1");if(d.feats.have(k,l)){D=true;break}I.push(E.row(k).field("feat"));break;case"race":if(U&&y){continue}U=true;t=r.field("reqparam1");if(c.race.base_id==t){y=true;break}o.push(n.row(t).field("name"));break;case"subrace":t=r.field("reqparam1");if(c.race.id!=t){s.error("Race Restrictions",Q.row(t).field("name"))}break;case"bab":O=r.field("reqparam1");if(L.value<O){s.error("Minimum Attack Bonus","+"+O)}break;case"arcspell":O=r.field("reqparam1");if(ac.arcane.high<(O+1)){s.error("Spell Level Requirements","Arcane Level "+O)}break;case"divspell":O=r.field("reqparam1");if(ac.divine.high<(O+1)){s.error("Spell Level Requirements","Divine Level "+O)}break;case"arcspellor":if(A&&e){continue}A=true;O=r.field("reqparam1");if(ac.arcane.high>(O+1)){e=true;break}w.push("Arcane Level "+O);break;case"divspellor":if(A&&e){continue}A=true;O=r.field("reqparam1");if(ac.divine.high>(O+1)){e=true;break}w.push("Divine Level "+O);break;case"classor":if(C&&f){continue}C=true;O=r.field("reqparam1");if(builder.classLevel(l,O)>0){f=true;break}M.push(v.row(O).field("name"));break;case"classnot":O=r.field("reqparam1");if(builder.classLevel(l,O)>0){break}Y.push(v.row(O).field("name"));break;case"skill":W=r.field("reqparam1",b.ID_NONE);h=r.field("reqparam2",b.ID_NONE);if(W>=b.ID_NONE){K=0;S=q.length;while(S--){if(q[S].id==W){K=q[S].value_raw;break}}if(h!=b.ID_NONE&&K<h){s.warning("Skill Requirements",G.row(W).field("name")+" "+h)}}break}}if(F.length){for(V=0;V<F.length;V++){s.error("Feats Required",F[V])}}if(Z&&!D){for(V=0;V<I.length;V++){if(V>10){s.error("One Feat Required",(I.length-10)+" More... (See Class Description)");break}s.error("One Feat Required",I[V])}}if(U&&!y){for(V=0;V<o.length;V++){s.error("Race Required",o[V])}}if(A&&!e){for(V=0;V<w.length;V++){s.error("One Spell Level Required",w[V])}}if(C&&!f){for(V=0;V<M.length;V++){s.error("One Class Required",M[V])}}if(Y.length){for(V=0;V<Y.length;V++){s.error("Cannot Be Class",Y[V])}}}}return s},change:function(m,j,g){if(j===undefined){j=1}if(g===undefined){g=false}var e=a.max_store_level;if(g==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_CLASS,{level:build.classes.level,count:j,id:m})}var l=(new dataTable()).table("classes").row(m);var h,f,k;j=this.level+j;for(h=this.level;h<j;h++){if(h<1||h>e){continue}k=c.level[h];k.class_id=m;k.class_icon=l.field("borderedicon");k.class_label=l.field("name");k.class_spellcaster=l.field("spellcaster");k.prestige=(l.field("prereqtable")!=b.ID_NONE)?1:0;k.table_feats=l.field("featstable");switch(l.field("spellabil")){case"str":k.class_ability_spell=b.ABILITY_STR;break;case"dex":k.class_ability_spell=b.ABILITY_DEX;break;case"con":k.class_ability_spell=b.ABILITY_CON;break;case"int":k.class_ability_spell=b.ABILITY_INT;break;case"wis":k.class_ability_spell=b.ABILITY_WIS;break;case"cha":k.class_ability_spell=b.ABILITY_CHA;break}switch(l.field("primaryabil")){case"str":k.class_ability_spell_dc=b.ABILITY_STR;break;case"dex":k.class_ability_spell_dc=b.ABILITY_DEX;break;case"con":k.class_ability_spell_dc=b.ABILITY_CON;break;case"int":k.class_ability_spell_dc=b.ABILITY_INT;break;case"wis":k.class_ability_spell_dc=b.ABILITY_WIS;break;case"cha":k.class_ability_spell_dc=b.ABILITY_CHA;break}k.class_hit_die=l.field("hitdie");k.class_skill=l.field("skillpointbase")}if(!g){this.calculateSaves()}if(this.level<1){this.level=1}if(this.level>e){this.level=e}builder.log("class","Changed level "+this.level+" to ["+m+"] "+c.level[this.level].class_label);return(g==true)?true:build.changed(this.level)},fetch:function(e){this.level=e;var g=[];var h=[];var l=[];var m=[];var k=[];var o=(new dataTable()).table("classes");var n=o.data.length;var p,f;for(var j=0;j<n;j++){p=o.row(false,j);f=p.field("a_id");if(!p.field("playerclass")){continue}if(p.field("hitdie")==-1){continue}if(p.field("prereqtable")==-1){if(!build.classes.validate(f,false,e).valid){h.push({id:f,icon:p.field("borderedicon"),label:p.field("name"),hover:p.field("description")})}else{g.push({id:f,icon:p.field("borderedicon"),label:p.field("name"),hover:p.field("description")})}}else{if(!build.classes.validate(f,false,e).valid){m.push({id:f,icon:p.field("borderedicon"),label:p.field("name"),hover:p.field("description")})}else{l.push({id:f,icon:p.field("borderedicon"),label:p.field("name"),hover:p.field("description")})}}}k.push({title:"Base Classes",feats:g,disabled:h});k.push({title:"Prestige Classes",feats:l,disabled:m});return{title:"Select Class",categories:k,selected:[c.level[e].class_id]}},calculateSpellLevels:function(){builder.log("class","Calculating Spell Levels");var o=(new dataTable()).table("classes");var q=a.max_level;var e,k,p,r,h,f;var g=[];var m,n,l;for(var j=1;j<=q;j++){e=c.level[j];h=e.class_id;m=d.caster.fetch(j);if(e.caster.progress!=b.ID_NONE){l=e.caster.progress}else{l=h}e.spell.arcane=0;e.spell.divine=0;e.spell.invoke=0;k=o.row(l);p=k.field("spellgaintable");if(p!=b.ID_NONE){p=(new dataTable()).table(p);if(k.field("hasarcane")==1){n=(m.arcane.classes[l]===undefined)?0:m.arcane.classes[l].level;e.spell.arcane=p.row(n-1).field("numspelllevels")}if(k.field("hasdivine")==1){n=(m.divine.classes[l]===undefined)?0:m.divine.classes[l].level;e.spell.divine=p.row(n-1).field("numspelllevels")}if([39,61].find(l)){n=(m.invoke.classes[l]===undefined)?0:m.invoke.classes[l].level;e.spell.invoke=p.row(n-1).field("numspelllevels")}}}},calculateCasterLevels:function(){builder.log("class","Calculating Caster Levels");var s=(new dataTable()).table("classes");var t=a.max_level;var l,n,v,e,h,p,o,r,u,q;var g=[];var k,f;for(var m=1;m<=t;m++){e=c.level[m];l=e.class_id;q=l;n=s.row(l);h=n.field("bonuscasterfeatbyclassmap");if(h!=b.ID_NONE){v=n.field("bonusspellcasterleveltable");if(g[l]===undefined){h=(new dataTable()).table(h);o=h.data.length;for(k=0;k<o;k++){u=h.row(false,k);p=u.field("spellcasterfeat");if(p==b.ID_NONE){continue}if(d.feats.have(p,m)){r=u.field("classid");g[l]=r;u=s.row(r);l=g[l];break}}}else{u=s.row(g[l]);l=g[l]}v=(new dataTable()).table(v);f=builder.classLevel(m,q);if(v.row(false,(f-1)).field("grantsbonusspellcasterlevel")!=1){l=b.ID_NONE}else{n=s.row(l)}}if(l==b.ID_NONE){e.caster.arcane=0;e.caster.divine=0;e.caster.invoke=0;e.caster.progress=l}else{e.caster.arcane=(n.field("hasarcane")==1)?1:0;e.caster.divine=(n.field("hasdivine")==1)?1:0;e.caster.invoke=([39,61].find(l))?1:0;e.caster.progress=l}}},calculateBAB:function(){builder.log("class","Calculating BAB");var j=(new dataTable()).table("classes");var e=a.max_level;var g,k,h;for(var f=1;f<=e;f++){g=c.level[f].class_id;k=builder.classLevel(f,g);h=j.row(g).field("attackbonustable");h=(new dataTable()).table(h).row(k-1);c.level[f].bab=h.field("bab")}},calculateSaves:function(){builder.log("class","Calculating Saving Throws");var j=(new dataTable()).table("classes");var e=a.max_level;var g,k,h;for(var f=1;f<=e;f++){g=c.level[f].class_id;k=builder.classLevel(f,g);c.level[f].class_level=k;h=j.row(g).field("savingthrowtable");h=(new dataTable()).table(h).row(k-1);c.level[f].save.fortitude=h.field("fortsave");c.level[f].save.reflex=h.field("refsave");c.level[f].save.will=h.field("willsave")}},findLevelByClassLevel:function(g,h){var e=a.max_level;for(var f=1;f<=e;f++){if(c.level[f].class_id!=g){continue}if(c.level[f].class_level==h){return f}}return false}}})();builder.tick("Module: Abilities");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.ability={change:function(g,f,e){if(e===undefined){e=false}if(e==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_ABILITY,{level:g,id:f})}c.level[g].ability=f;return(e==true)?true:build.changed()},changeEpicRelevel:function(e,h){var g=0,f=6;while(f--){g+=parseInt(c.ability.ROT[e][f])}if(g>=a.rot_epic_relevel_points){return false}if(!c.ability.ROT[e][h]){c.ability.ROT[e][h]=0}c.ability.ROT[e][h]++;return build.changed()},changeROTExtraAbility:function(g){var f=0,e=6;while(e--){f+=parseInt(c.ability.ROTE[e])}if(f>=a.rot_epic_relevel_points){return false}if(!c.ability.ROTE[g]){c.ability.ROTE[g]=0}c.ability.ROTE[g]++;return build.changed()}}})();builder.tick("Module: Backgrounds");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.background={validate:function(g,k){var r=new buildValidator();if(k===undefined){k=(new dataTable()).table("backgrounds").row(g)}var q=d.bab.fetch(1,b.FEAT_TYPE_AUTO);var p=k.field("minattackbonus");if(q.value<p){r.error("Minimum Attack Bonus","+"+p)}var l=d.abilities.fetch(1,b.FEAT_TYPE_AUTO);p=k.field("minstr",0);if(p!=b.ID_NONE&&l[b.ABILITY_STR].value<p){r.error("Minimum Ability Score","Strength: "+p)}p=k.field("mindex",0);if(p!=b.ID_NONE&&l[b.ABILITY_DEX].value<p){r.error("Minimum Ability Score","Dexterity: "+p)}p=k.field("mincon",0);if(p!=b.ID_NONE&&l[b.ABILITY_CON].value<p){r.error("Minimum Ability Score","Constitution: "+p)}p=k.field("minint",0);if(p!=b.ID_NONE&&l[b.ABILITY_INT].value<p){r.error("Minimum Ability Score","Intelligence: "+p)}p=k.field("minwis",0);if(p!=b.ID_NONE&&l[b.ABILITY_WIS].value<p){r.error("Minimum Ability Score","Wisdom: "+p)}p=k.field("mincha",0);if(p!=b.ID_NONE&&l[b.ABILITY_CHA].value<p){r.error("Minimum Ability Score","Charisma: "+p)}p=k.field("maxstr",99);if(p!=b.ID_NONE&&l[b.ABILITY_STR].value>p){r.error("Maximum Ability Score","Strength: "+p)}p=k.field("maxdex",99);if(p!=b.ID_NONE&&l[b.ABILITY_DEX].value>p){r.error("Maximum Ability Score","Dexterity: "+p)}p=k.field("maxcon",99);if(p!=b.ID_NONE&&l[b.ABILITY_CON].value>p){r.error("Maximum Ability Score","Constitution: "+p)}p=k.field("maxint",99);if(p!=b.ID_NONE&&l[b.ABILITY_INT].value>p){r.error("Maximum Ability Score","Intelligence: "+p)}p=k.field("maxwis",99);if(p!=b.ID_NONE&&l[b.ABILITY_WIS].value>p){r.error("Maximum Ability Score","Wisdom: "+p)}p=k.field("maxcha",99);if(p!=b.ID_NONE&&l[b.ABILITY_CHA].value>p){r.error("Maximum Ability Score","Charisma: "+p)}var h;var e=false;var m=false;var f=3;var n=[];var o=(new dataTable()).table("classes");for(var j=0;j<f;j++){h=k.field("orreqclass"+j,b.ID_NONE);if(h!=b.ID_NONE){m=true;n.push(o.row(h).field("name"))}if(h==c.level[1].class_id){e=true;break}}if(m&&!e){for(j=0;j<n.length;j++){r.error("Class Requirements",n[j])}}return r},change:function(j,e){if(e===undefined){e=false}var h=(new dataTable()).table("backgrounds").row(j);if(e==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_BACKGROUND,j)}c.background.id=j;c.background.icon=h.field("icon");c.background.label=h.field("name");c.background.feats=[];var g=h.field("displayfeat");if(g!=b.ID_NONE){var f=(new dataTable()).table("feat");var g=f.row(g);c.background.feats.push({id:g.field("a_id"),label:g.field("feat"),type:b.FEAT_TYPE_AUTO,category:g.field("featcategory")})}builder.log("trait","Changed to ["+j+"] "+c.background.label);return(e==true)?true:build.changed()},fetch:function(){var k=[];var g=[];var j=[];var m=(new dataTable()).table("backgrounds");var l=m.data.length;var n,f,e;for(var h=0;h<l;h++){n=m.row(false,h);e=n.field("a_id");if(!build.background.validate(e,n).valid){g.push({id:e,icon:n.field("icon"),label:n.field("name"),hover:n.field("description")})}else{k.push({id:e,icon:n.field("icon"),label:n.field("name"),hover:n.field("description")})}}j.push({title:"Backgrounds",feats:k,disabled:g});return{title:"Select Background Trait",categories:j,selected:[c.background.id]}}}})();builder.tick("Module: Racial Types");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.race={change:function(m,f){if(f===undefined){f=false}if(m==49){m=67}if(m==50){m=68}var e=(new dataTable()).table("racialsubtypes");var l=e.row(m);if(f==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_RACE,m)}c.race.id=m;c.race.icon=l.field("male_race_icon");c.race.label=l.field("name");c.race.feats=[];c.race.base_id=l.field("baserace");c.race.ecl=l.field("ecl");c.race.favored=(l.field("hasfavoredclass")!=1)?b.ID_NONE:l.field("favored");c.race.ability=[l.field("stradjust"),l.field("dexadjust"),l.field("conadjust"),l.field("intadjust"),l.field("wisadjust"),l.field("chaadjust")];var h=(new dataTable()).table("feat");var k=(new dataTable()).table(l.field("featstable"));var g=k.data.length;var j;while(g--){j=h.row(k.row(false,g).field("featindex"));c.race.feats.push({id:j.field("a_id"),label:j.field("feat"),type:b.FEAT_TYPE_AUTO,category:j.field("featcategory")})}builder.log("race","Changed to ["+m+"] "+c.race.label);if(f!=true){build.forceChange=true}return(f==true)?true:build.changed()},fetch:function(){var n=[];var m=[];var g=(new dataTable()).table("racialtypes");var h=(new dataTable()).table("racialsubtypes");var e=g.data.length;var k=h.data.length;var q,o,f,p;for(var l=0;l<e;l++){q=g.row(false,l);if(q.field("playerrace")!=1){continue}p=q.field("a_id");n=[];for(f=0;f<k;f++){o=h.row(false,f);if(o.field("playerrace")!=1){continue}if(o.field("baserace")!=p){continue}n.push({id:o.field("a_id"),icon:o.field("male_race_icon"),label:o.field("name"),hover:o.field("description")})}m.push({title:q.field("name"),feats:n,disabled:[]})}return{title:"Select Race",categories:m,selected:[c.race.id]}}}})();builder.tick("Module: Alignments");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.alignment={validate:function(){var e=new buildValidator();var g=(new dataTable()).table("classes").row(c.level[1].class_id);var j=g.field("alignrestrict",0);var f=g.field("alignrstrcttype",0);var h=g.field("invertrestrict",0);if(build.alignment.restricted(j,f,h)){e.error("Class Restrictions","Invalid alignment for <em>"+g.field("name")+"</em>")}return e},change:function(h,e){if(e===undefined){e=false}var g=(new dataTable()).table("iprp_alignment").row(h);if(e==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_ALIGNMENT,h)}c.alignment.id=h;c.alignment.label=g.field("name");var f=["align_lg","align_ln","align_le","align_ng","align_n","align_ne","align_cg","align_cn","align_ce"];c.alignment.icon=f[h];builder.log("align","Changed to ["+h+"] "+c.alignment.label);return(e==true)?true:build.changed()},fetch:function(){var h=[];var g=[];var l=["align_lg","align_ln","align_le","align_ng","align_n","align_ne","align_cg","align_cn","align_ce"];var f=["a0","b0","c0","a1","b1","c1","a2","b2","c2"];var m=(new dataTable()).table("iprp_alignment");var j=m.data.length;var k=0,n;for(var e=0;e<j;e++){n=m.row(false,e);h.push({id:n.field("a_id"),icon:l[k],label:n.field("name"),sort_label:f[k],hover:n.field("description")});k++}g.push({title:"Alignment",feats:h,disabled:[]});return{title:"Select Alignment",categories:g,selected:[c.alignment.id]}},axis:function(e){switch(c.alignment.id){case 0:if(e&b.ALIGN_AXIS_LAWFUL_GOOD){return true}break;case 1:if(e&b.ALIGN_AXIS_LAWFUL_NEUTRAL){return true}break;case 2:if(e&b.ALIGN_AXIS_LAWFUL_EVIL){return true}break;case 3:if(e&b.ALIGN_AXIS_NEUTRAL_GOOD){return true}break;case 4:if(e&b.ALIGN_AXIS_NEUTRAL){return true}break;case 5:if(e&b.ALIGN_AXIS_NEUTRAL_EVIL){return true}break;case 6:if(e&b.ALIGN_AXIS_CHAOTIC_GOOD){return true}break;case 7:if(e&b.ALIGN_AXIS_CHAOTIC_NEUTRAL){return true}break;case 8:if(e&b.ALIGN_AXIS_CHAOTIC_EVIL){return true}break}return false},restricted:function(o,e,h){if(!o){o=0}if(!e){e=0}var m=1;var l=2;var p=4;var j=8;var g=16;var f=[];o=parseInt(o);e=parseInt(e);if((o&l)==l){f.push(0,1,2)}if((o&p)==p){f.push(6,7,8)}if((o&j)==j){f.push(0,3,6)}if((o&g)==g||(o==20)){f.push(2,5,8)}if((o&m)==m){switch(e){case 1:f.push(3,4,5);break;case 2:f.push(1,4,7);break;case 3:f.push(1,3,4,5,7);break}}var n=f.length;var q=false;for(var k=0;k<n;k++){if(c.alignment.id==f[k]){q=true;break}}if(h==true){q=(q==true)?false:true}return q}}})();builder.tick("Module: Deities");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.deity={validate:function(f,k){var q=new buildValidator();if(k===undefined){k=(new dataTable()).table("nwn2_deities").row(f)}var g;var n=[{id:0,field:"lg",check:build.alignment.axis(b.ALIGN_AXIS_LAWFUL_GOOD)},{id:1,field:"ng",check:build.alignment.axis(b.ALIGN_AXIS_NEUTRAL_GOOD)},{id:2,field:"cg",check:build.alignment.axis(b.ALIGN_AXIS_CHAOTIC_GOOD)},{id:3,field:"ln",check:build.alignment.axis(b.ALIGN_AXIS_LAWFUL_NEUTRAL)},{id:4,field:"tn",check:build.alignment.axis(b.ALIGN_AXIS_NEUTRAL)},{id:5,field:"cn",check:build.alignment.axis(b.ALIGN_AXIS_CHAOTIC_NEUTRAL)},{id:6,field:"le",check:build.alignment.axis(b.ALIGN_AXIS_LAWFUL_EVIL)},{id:7,field:"ne",check:build.alignment.axis(b.ALIGN_AXIS_NEUTRAL_EVIL)},{id:8,field:"ce",check:build.alignment.axis(b.ALIGN_AXIS_CHAOTIC_EVIL)}];for(var l=0;l<n.length;l++){if(!n[l].check){continue}g=k.field(n[l].field);switch(g){case 0:q.error("Restrictions","None can follow this deity");break;case 1:if(![2,3,6,7].find(c.level[1].class_id)){q.valid=true}break;case 2:if([2,3,6,7].find(c.level[1].class_id)){q.valid=true}break}}if(!k.field("allraces",0)){var j;var e=9;var h=false;var m=false;var o=[];var p=(new dataTable()).table("racialsubtypes");for(var l=1;l<=e;l++){j=k.field("subraceid"+l);if(j==b.ID_NONE){continue}h=true;o.push(p.row(j).field("name"));if(c.race.id==j){m=true;break}}if(h&&!m){for(l=0;l<o.length;l++){q.error("Race Requirements",o[l])}}}switch(c.level[1].class_id){case 2:switch(k.field("cleric")){case 0:q.error("Class Restrictions","Cannot be chosen by <em>Cleric</em>");break;case 2:q.valid=true;break}break;case 3:switch(k.field("druid")){case 0:q.error("Class Restrictions","Cannot be chosen by <em>Druid</em>");break;case 2:q.valid=true;break}break;case 6:switch(k.field("paladin")){case 0:q.error("Class Restrictions","Cannot be chosen by <em>Paladin</em>");break;case 2:q.valid=true;break}break;case 7:switch(k.field("ranger")){case 0:q.error("Class Restrictions","Cannot be chosen by <em>Ranger</em>");break;case 2:q.valid=true;break}break}return q},change:function(h,f){if(f===undefined){f=false}var g=(new dataTable()).table("nwn2_deities").row(h);var e=g.field("firstname").toTitleCase();if(g.field("lastname")!=-1){e+=" "+g.field("lastname").toTitleCase()}if(f==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_DEITY,h)}c.deity.id=h;c.deity.icon=g.field("iconid");c.deity.label=e;builder.log("deity","Changed to ["+h+"] "+c.deity.label);return(f==true)?true:build.changed()},fetch:function(){var l=[];var g=[];var k=[];var n=(new dataTable()).table("nwn2_deities");var o=(new dataTable()).table("feat");var m=n.data.length;var p,f,j,e;for(var h=0;h<m;h++){p=n.row(false,h);if(p.field("removed")==1){continue}f=p.field("firstname");if(p.field("lastname")!=-1){f+=" "+p.field("lastname")}f=f.toTitleCase();j=(f=="No Deity")?" "+f:f;e=p.field("favoredweaponfocus");if(e!=b.ID_NONE){e=o.row(e).field("feat","");e=(e!="")?"<em>"+e.substr(14,e.length-15)+"</em>":""}else{e=""}if(!build.deity.validate(b.ID_NONE,p).valid){g.push({id:p.field("a_id"),icon:p.field("iconid"),label:e+f,sort_label:j,hover:p.field("descid")})}else{l.push({id:p.field("a_id"),icon:p.field("iconid"),label:e+f,sort_label:j,hover:p.field("descid")})}}k.push({title:"Deities",feats:l,disabled:g});return{title:"Select Deity",categories:k,selected:[c.deity.id]}}}})();builder.tick("Module: Cleric Domains");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.domain={slot:0,level:1,change:function(j,h,f){if(h===undefined){h=this.slot}if(f===undefined){f=false}if(f==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_DOMAIN,{slot:h,id:j})}var g=(new dataTable()).table("domains").row(j);var e=(new dataTable()).table("feat");c.domain[h]={id:j,label:g.field("name"),icon:g.field("icon"),feats:[{id:g.field("grantedfeat"),label:e.row(g.field("grantedfeat")).field("feat"),type:b.FEAT_TYPE_AUTO,category:g.field("featcategory")}]};builder.log("domain","Changed to ["+j+"] "+g.field("name"));return(f==true)?true:build.changed()},fetch:function(e,m){this.slot=m;this.level=e;var j=[];var h=[];var f=[];var n=(new dataTable()).table("domains");var k=n.data.length;var o,l;for(var g=0;g<k;g++){o=n.row(false,g);l=o.field("icon");if(l==b.ID_NONE){continue}if(c.domain[(m==0)?1:0].id==o.field("a_id")){f.push({id:o.field("a_id"),icon:l,label:o.field("name"),hover:o.field("description")})}else{j.push({id:o.field("a_id"),icon:l,label:o.field("name"),hover:o.field("description")})}}h.push({title:"Domains",feats:j,disabled:f});return{title:"Select Domain",categories:h,selected:[c.domain[m].id]}}}})();builder.tick("Module: Spell Schools");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.school={level:1,change:function(g,e){if(e===undefined){e=false}var f=(new dataTable()).table("spellschools").row(g);if(e==false&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_SCHOOL,g)}c.school.id=g;c.school.icon=f.field("icon");c.school.label=f.field("stringref");builder.log("school","Changed to ["+g+"] "+c.school.label);return(e==true)?true:build.changed()},fetch:function(l){this.level=l;var g=[];var e=[];var j=(new dataTable()).table("spellschools");var h=j.data.length;var k;for(var f=0;f<h;f++){k=j.row(false,f);g.push({id:k.field("a_id"),icon:k.field("icon"),label:k.field("stringref"),hover:k.field("description")})}e.push({title:"Spell Schools",feats:g,disabled:[]});return{title:"Select Animal Companion",categories:e,selected:[c.school.id]}}}})();builder.tick("Module: Animal Companions");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.animal={level:1,validate:function(j,h){var e=new buildValidator();var g=(new dataTable()).table("hen_companion").row(j);var f=g.field("featid",b.ID_NONE);if(f!=b.ID_NONE&&!d.feats.have(f,h)){e.error("Feats Required",(new dataTable()).table("feat").row(f).field("feat"))}return e},change:function(j,e){if(e===undefined){e=false}var g=c.level[this.level].class_id;var h=(new dataTable()).table("hen_companion").row(j);if(e==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_ANIMAL,{level:this.level,id:j})}var f=(j==b.ID_NONE||!h)?"":h.field("baseresref_prefix").replace("c_ancom_","ico_");if(f=="ico_bronze"){f="ico_bronze_dragon_young"}if(f=="ico_blue"){f="ico_blue_dragon_young"}if(f=="ico_dino"){f="ico_deinonychus"}if(f=="cmi_ancom_elef"){f="ico_elmfirehuge"}if(f=="cmi_ancom_elea"){f="ico_elmairhuge"}if(f=="cmi_ancom_elew"){f="ico_elmwaterhuge"}if(f=="cmi_ancom_elee"){f="ico_elmearthhuge"}c.animal[g]={id:j,icon:f,label:h.field("strref"),level:this.level,class_level:c.level[this.level].class_level};builder.log("animal","Changed to ["+j+"] "+c.animal[g].label);return(e==true)?true:build.changed()},fetch:function(e){this.level=e;var k=[];var j=[];var o=(new dataTable()).table("hen_companion");var l=o.data.length;var p,n,m;for(var h=0;h<l;h++){p=o.row(false,h);if(p.field("availabletoplayer")!=1){continue}m=p.field("featid",b.ID_NONE);if(m!=b.ID_NONE){if(!d.feats.have(m,e)){continue}}n=p.field("baseresref_prefix").replace("c_ancom_","ico_");if(n=="ico_bronze"){n="ico_bronze_dragon_young"}if(n=="ico_blue"){n="ico_blue_dragon_young"}if(n=="ico_dino"){n="ico_deinonychus"}if(n=="cmi_ancom_elef"){n="ico_elmfirehuge"}if(n=="cmi_ancom_elea"){n="ico_elmairhuge"}if(n=="cmi_ancom_elew"){n="ico_elmwaterhuge"}if(n=="cmi_ancom_elee"){n="ico_elmearthhuge"}k.push({id:p.field("a_id"),icon:n,label:p.field("strref"),hover:p.field("description")})}j.push({title:"Animal Companions",feats:k,disabled:[]});var g=[];var f=c.level[e].class_id;if(c.animal[f]!==undefined){g=[c.animal[f].id]}return{title:"Select Animal Companion",categories:j,selected:g}}}})();builder.tick("Module: Familiars");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.familiar={level:1,change:function(l,e){if(e===undefined){e=false}var j=c.level[this.level].class_id;var k=(new dataTable()).table("hen_familiar").row(l);if(e==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_FAMILIAR,{level:this.level,id:l})}var h=(l==b.ID_NONE)?"":k.field("baseresref_prefix").replace("c_fam_","ico_");if(h=="ico_beetle"){h="ico_beetle_stag"}var f=(new dataTable()).table("feat");var g=f.row(k.field("featgained"));c.familiar[j]={id:l,icon:h,label:k.field("strref"),feat:{id:g.field("a_id"),label:g.field("feat"),type:b.FEAT_TYPE_AUTO},level:this.level,class_level:c.level[this.level].class_level};builder.log("familiar","Changed to ["+l+"] "+c.familiar[j].label);return(e==true)?true:build.changed()},fetch:function(e){this.level=e;var k=[];var j=[];var n=(new dataTable()).table("hen_familiar");var l=n.data.length;var o,m;for(var h=0;h<l;h++){o=n.row(false,h);if(o.field("availabletoplayer")!=1){continue}m=o.field("baseresref_prefix").replace("c_fam_","ico_");if(m=="ico_beetle"){m="ico_beetle_stag"}k.push({id:o.field("a_id"),icon:m,label:o.field("strref"),hover:o.field("description")})}j.push({title:"Familiars",feats:k,disabled:[]});var g=[];var f=c.level[e].class_id;if(c.familiar[f]!==undefined){g=[c.familiar[f].id]}return{title:"Select Familiar",categories:j,selected:g}}}})();builder.tick("Module: Feats");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.feat={level:1,type:b.FEAT_TYPE_NORMAL,slot:0,_clone:function(f,e){return{id:f.id,label:f.label,icon:f.icon,type:e,category:f.category}},validate:function(g,f,l,m,G,s){var z=new buildValidator();if(g==b.ID_NONE){z.valid=false;return z}var k=(new dataTable()).table("feat");var O=(new dataTable()).table("feat").row(g);if(G===undefined){G=O.field("category")}if(G=="****"||G=="history_ft_cat"){z.valid=false;return z}if(G=="background_ft_cat"&&build.feat.hasBackground(l,m)){z.valid=false;return z}if(s===undefined){s=false}var I=(new dataTable()).table("classes");var w=[];var F,x;if(O.field("removed")==1){z.valid=false;return z}if(O.field("prereqepic")==1&&f<21){if(s==true){z.valid=false;return z}z.error("Character Restrictions","Requires Epic Level")}var M=O.field("minlevelclass");F=O.field("maxlevel",false);if(F>0){if(M!=-1){if(builder.classLevel(f,M)>F){if(s==true){z.valid=false;return z}z.error("Character Restrictions","Exceeded Maximum Level ("+F+")")}}else{if(f>F){if(s==true){z.valid=false;return z}z.error("Character Restrictions","Exceeded Maximum Level ("+F+")")}}}var E=d.spell.fetch(f,m);F=O.field("minspelllvl");if([E.arcane.high,E.divine.high].high()<F){if(s==true){z.valid=false;return z}z.error("Minimum Spell Level","Divine or Arcane Level "+F)}var u=d.caster.fetch(f,m);F=O.field("mincasterlvl");if([u.arcane.high,u.divine.high,u.invoke.high].high()<F){if(s==true){z.valid=false;return z}z.error("Minimum Caster Level","Level "+F)}F=O.field("minlevel");if(M!=-1&&builder.classLevel(f,M)<F){if(s==true){z.valid=false;return z}z.error("Class Requirements",I.row(M).field("name")+" Level "+F)}var p=d.saves.fetch(f,m);F=O.field("minfortsave");if(F>0&&p[b.SAVING_THROW_FORT].value<F){if(s==true){z.valid=false;return z}z.error("Saving Throw Requirements","Fortitude "+F)}var C=d.bab.fetch(f,m);F=O.field("minattackbonus",0);if(C.value<F){if(s==true){z.valid=false;return z}z.error("Minimum Attack Bonus","+"+F)}var t=d.abilities.fetch(f,m);F=O.field("minstr",0);if(t[b.ABILITY_STR].value<F){if(s==true){z.valid=false;return z}z.error("Minimum Ability Score","Strength "+F)}F=O.field("mindex",0);if(t[b.ABILITY_DEX].value<F){if(s==true){z.valid=false;return z}z.error("Minimum Ability Score","Dexterity "+F)}F=O.field("mincon",0);if(t[b.ABILITY_CON].value<F){if(s==true){z.valid=false;return z}z.error("Minimum Ability Score","Constitution "+F)}F=O.field("minint",0);if(t[b.ABILITY_INT].value<F){if(s==true){z.valid=false;return z}z.error("Minimum Ability Score","Intelligence "+F)}F=O.field("minwis",0);if(t[b.ABILITY_WIS].value<F){if(s==true){z.valid=false;return z}z.error("Minimum Ability Score","Wisdom "+F)}F=O.field("mincha",0);if(t[b.ABILITY_CHA].value<F){if(s==true){z.valid=false;return z}z.error("Minimum Ability Score","Charisma "+F)}if(d.feats.have(g,f,m,false,l)){if(s==true){z.valid=false;return z}z.error("Selection Error","Duplicate Feat")}var v=O.field("prereqfeat1");if(v>=0&&!d.feats.have(v,f,m,false,l)){if(v==1932){if(d.feats.have(339,f,m)&&d.feats.have(3755,f,m)){}else{if(s==true){z.valid=false;return z}z.error("Feat Requirements",k.row(v).field("feat"))}}else{if(s==true){z.valid=false;return z}z.error("Feat Requirements",k.row(v).field("feat"))}}v=O.field("prereqfeat2");if(v>=0&&!d.feats.have(v,f,m,false,l)){if(s==true){z.valid=false;return z}z.error("Feat Requirements",k.row(v).field("feat"))}var N=false;var q=false;var h=[];for(var H=0;H<=5;H++){if(N){continue}v=O.field("orreqfeat"+H);if(v>=0){q=true;if(d.feats.have(v,f,m)){N=true}}if(!s){h.push(k.row(v).field("feat"))}}if(q&&!N){if(s==true){z.valid=false;return z}for(H=0;H<h.length;H++){z.error("One Feat Required",h[H])}}if(m!=b.FEAT_TYPE_SUBSELECT&&O.field("allclassescanuse",b.ID_NONE)!=1){var D=c.level[f].class_id;if(w[D]===undefined){w[D]=I.row(D)}var L=(new dataTable()).table(w[D].field("featstable"));var K=L.data.length;var B=false;for(H=0;H<K;H++){if(L.row(false,H).field("featindex")==g){switch(L.row(false,H).field("list")){case 0:case 1:B=true;break;case 2:if(m==b.FEAT_TYPE_BONUS||m==b.FEAT_TYPE_SUBSELECT){B=true}break}break}}if(!B){if(s==true){z.valid=false;return z}z.error("Class Restrictions","Not Available to Class")}}switch(O.field("alignrestrict")){case 2:if(build.alignment.axis(b.ALIGN_AXIS_LAWFUL)==true){if(s==true){z.valid=false;return z}z.error("Alignment Restrictions","Cannot be Lawful")}break;case 3:if(build.alignment.axis(b.ALIGN_AXIS_CHAOTIC)==true){if(s==true){z.valid=false;return z}z.error("Alignment Restrictions","Cannot be Chaotic")}break;case 4:if(build.alignment.axis(b.ALIGN_AXIS_GOOD)==true){if(s==true){z.valid=false;return z}z.error("Alignment Restrictions","Cannot be Good")}break;case 5:if(build.alignment.axis(b.ALIGN_AXIS_EVIL)==true){if(s==true){z.valid=false;return z}z.error("Alignment Restrictions","Cannot be Evil")}break}var J=(new dataTable()).table("skills");var e=d.skills.fetch(f);var y=O.field("reqskill",b.ID_NONE);var o=O.field("reqskillminranks",b.ID_NONE);var r=O.field("reqskillmaxranks",b.ID_NONE);var A,n;if(y>=b.ID_NONE){n=J.row(y).field("name");A=0;H=e.length;while(H--){if(e[H].id==y){A=e[H].value_raw;break}}if(o!=b.ID_NONE&&A<o){if(s==true){z.valid=true;return z}z.warning("Skill Requirements",n+": Minimum "+o)}if(r!=b.ID_NONE&&A>r){if(s==true){z.valid=true;return z}z.warning("Skill Requirements",n+": Maximum "+r)}}y=O.field("reqskill2",b.ID_NONE);o=O.field("reqskillminranks2",b.ID_NONE);r=O.field("reqskillmaxranks2",b.ID_NONE);if(y>=b.ID_NONE){n=J.row(y).field("name");A=0;H=e.length;while(H--){if(e[H].id==y){A=e[H].value_raw;break}}if(o!=b.ID_NONE&&A<o){if(s==true){z.valid=true;return z}z.warning("Skill Requirements",n+": Minimum "+o)}if(r!=b.ID_NONE&&A>r){if(s==true){z.valid=true;return z}z.warning("Skill Requirements",n+": Maximum "+r)}}return z},get:function(h,l,k,g,j){if(h==b.FEAT_TYPE_BONUS||h==b.FEAT_TYPE_SUBSELECT){g=c.level[l].class_id;j=builder.classLevel(l,g)}if(k===undefined){k=0}if(k==-1){var f=[];switch(h){case b.FEAT_TYPE_NORMAL:if(c.feats.normal!==undefined&&c.feats.normal[l]!==undefined){for(var e in c.feats.normal[l]){f.push(this._clone(c.feats.normal[l][e],h))}return f}break;case b.FEAT_TYPE_BONUS:if(c.feats.bonus!==undefined&&c.feats.bonus[g]!==undefined&&c.feats.bonus[g][j]!==undefined){for(var e in c.feats.bonus[g][j]){f.push(this._clone(c.feats.bonus[g][j][e],h))}return f}break;case b.FEAT_TYPE_SUBSELECT:if(c.feats.subselect!==undefined&&c.feats.subselect[g]!==undefined&&c.feats.subselect[g][j]!==undefined){for(var e in c.feats.subselect[g][j]){f.push(this._clone(c.feats.subselect[g][j][e],h))}return f}break;case b.FEAT_TYPE_COMBAT_STYLE:if(c.feats.rcs!==undefined){return[this._clone(c.feats.rcs,h)]}break;case b.FEAT_TYPE_QUICK_TO_MASTER:if(c.feats.qtm!==undefined){return[this._clone(c.feats.qtm,h)]}break}return[]}else{switch(h){case b.FEAT_TYPE_NORMAL:if(c.feats.normal[l]!==undefined&&c.feats.normal[l][k]!==undefined){return this._clone(c.feats.normal[l][k])}break;case b.FEAT_TYPE_BONUS:if(c.feats.bonus[g]!==undefined&&c.feats.bonus[g][j]!==undefined&&c.feats.bonus[g][j][k]!==undefined){return this._clone(c.feats.bonus[g][j][k])}break;case b.FEAT_TYPE_SUBSELECT:if(c.feats.subselect[g]!==undefined&&c.feats.subselect[g][j]!==undefined&&c.feats.subselect[g][j][k]!==undefined){return this._clone(c.feats.subselect[g][j][k])}break;case b.FEAT_TYPE_COMBAT_STYLE:if(c.feats.rcs!==undefined&&c.feats.rcs.id!==undefined){return this._clone(c.feats.rcs)}break;case b.FEAT_TYPE_QUICK_TO_MASTER:if(c.feats.qtm!==undefined&&c.feats.qtm.id!==undefined){return this._clone(c.feats.qtm)}break}return{id:b.ID_NONE,label:"",icon:"",type:h,category:""}}},change:function(l,f){if(f===undefined){f=false}var e=c.feats;var j=(new dataTable()).table("feat").row(l);var h=j.field("feat");if(h===undefined&&l!==b.ID_NONE){return false}if(f==false&&!builder.output.pause){builder.history.add(b.HISTORY_SCOPE_FEAT,{level:this.level,slot:this.slot,type:this.type,id:l})}var g=c.level[this.level].class_id;var k=builder.classLevel(this.level,g);switch(this.type){case b.FEAT_TYPE_NORMAL:e.normal[this.level][this.slot]={id:l,icon:j.field("icon"),label:j.field("feat"),type:this.type,category:j.field("featcategory")};break;case b.FEAT_TYPE_SUBSELECT:if(e.subselect[g]===undefined){e.subselect[g]={}}e=e.subselect[g];if(e[k]===undefined){e[k]={}}e[k][this.slot]={id:l,icon:j.field("icon"),label:j.field("feat"),type:this.type,category:j.field("featcategory")};break;case b.FEAT_TYPE_BONUS:if(e.bonus[g]===undefined){e.bonus[g]={}}e=e.bonus[g];if(e[k]===undefined){e[k]={}}e[k][this.slot]={id:l,icon:j.field("icon"),label:j.field("feat"),type:this.type,category:j.field("featcategory")};break;case b.FEAT_TYPE_QUICK_TO_MASTER:e.qtm={id:l,icon:j.field("icon"),label:j.field("feat"),type:this.type,category:j.field("featcategory")};break;case b.FEAT_TYPE_COMBAT_STYLE:e.rcs={id:l,icon:j.field("icon"),label:j.field("feat"),type:b.FEAT_TYPE_SUBSELECT,category:j.field("featcategory")};break}builder.log("FEAT","Changed Feat for level "+this.level+" to "+l);return(f==true)?true:build.changed(1)},fetch:function(e,l,m){this.level=e;this.slot=l;this.type=m;var t=[{id:"racialability_ft_cat",title:"Racial Ability",feats:[],disabled:[]},{id:"classability_ft_cat",title:"Class Ability",feats:[],disabled:[]},{id:"general_ft_cat",title:"General Feats",feats:[],disabled:[]},{id:"proficiency_ft_cat",title:"Proficiency Feats",feats:[],disabled:[]},{id:"divine_ft_cat",title:"Divine Feats",feats:[],disabled:[]},{id:"spellcasting_ft_cat",title:"Spellcasting Feats",feats:[],disabled:[]},{id:"metamagic_ft_cat",title:"Metamagic Feats",feats:[],disabled:[]},{id:"itemcreation_ft_cat",title:"Item Creation Feats",feats:[],disabled:[]},{id:"skillnsave_ft_cat",title:"Skill and Save Feats",feats:[],disabled:[]},{id:"teamwork_ft_cat",title:"Teamwork Feats",feats:[],disabled:[]},{id:"background_ft_cat",title:"Background Feats",feats:[],disabled:[]},{id:"heritage_ft_cat",title:"Heritage Feats",feats:[],disabled:[]},{id:"epic_ft_cat",title:"Epic Feats",feats:[],disabled:[]}];var w,o,f,r;var n,v,u;var g=false;var q=[];var h=false;var p=builder.config.selector_group_feats;switch(m){case b.FEAT_TYPE_SUBSELECT:g=true;var z=c.level[e].table_feats;if(z!=b.ID_NONE){z=(new dataTable()).table(z);w=z.data.length;while(w--){n=z.row(false,w);if(n.field("grantedonlevel")<=e&&[1,2].find(n.field("list"))){q.push(n.field("featindex"))}}}break;case b.FEAT_TYPE_COMBAT_STYLE:g=true;q=[1729,1730,3887];var h=true;break}var k=(new dataTable()).table("feat");var y=[];var x=a.feat_groups.length;for(w=0;w<x;w++){y[w]={feats:[],ids:[]}}if(builder.debug){_START_DATE=new Date()}o=t.length;w=k.data.length;while(w--){n=k.row(false,w);f=n.field("a_id");if(g&&!q.find(f)){continue}u=n.field("featcategory");if(!h&&!build.feat.validate(f,e,l,m,u,true).valid){continue}v=x;r=false;if(p==true){while(v--){if(a.feat_groups[v].feats.find(f)){y[v].ids.push(f);y[v].feats.push({id:f,icon:n.field("icon"),label:n.field("feat"),hover:n.field("description")});r=true;break}}}if(!r){for(v=0;v<o;v++){if(t[v].id==u){t[v].feats.push({id:f,icon:n.field("icon"),label:n.field("feat"),hover:n.field("description")});break}}}}if(builder.debug){_END_DATE=new Date();builder.log("update","["+build.scope+"] Feats Processed in "+((_END_DATE.getTime()-_START_DATE.getTime())/1000)+"ms",1)}w=x;while(w--){if(y[w].feats.length<=0){continue}group=a.feat_groups[w];for(v=0;v<o;v++){if(t[v].id==group.category){t[v].feats.push({id:b.ID_NONE,icon:y[w].feats[0].icon,label:group.label,hover:y[w].feats[0].hover,group:true,group_feats:y[w].feats,group_feats_id:y[w].ids});break}}}var s=[];for(var w=0;w<o;w++){if(t[w].feats.length==0){continue}t[w].feats.sort(function(A,j){var C=A.label.toLowerCase();var B=j.label.toLowerCase();if(C<B){return -1}if(C>B){return 1}return 0});s.push(t[w])}return{title:"Select Feat",categories:s,selected:[this.get(m,e,l).id]}},hasBackground:function(j,g){var h,f;var e=(new dataTable()).table("feat");if(g!=b.FEAT_TYPE_QUICK_TO_MASTER){if(d.feats.have(a.featid_quick_to_master)){f=this.get(b.FEAT_TYPE_QUICK_TO_MASTER,1);if(f.id!=b.ID_NONE&&e.row(f.id).field("featcategory")=="background_ft_cat"){return true}}}if(g!=b.FEAT_TYPE_SUBSELECT){f=this.get(b.FEAT_TYPE_SUBSELECT,1,-1);h=f.length;while(h--){if(e.row(f[h].id).field("featcategory")=="background_ft_cat"){return true}}}if(g!=b.FEAT_TYPE_BONUS){f=this.get(b.FEAT_TYPE_BONUS,1,-1);h=f.length;while(h--){if(e.row(f[h].id).field("featcategory")=="background_ft_cat"){return true}}}if(g!=b.FEAT_TYPE_NORMAL){f=this.get(b.FEAT_TYPE_NORMAL,1,-1);h=f.length;while(h--){if(e.row(f[h].id).field("featcategory")=="background_ft_cat"){return true}}}return false},compileAutoFeats:function(e){builder.log("feat","Compiling Auto Feats");var y=a.max_level;var x,w,o,s,q,l;var r=b.ID_NONE;var A=(new dataTable()).table("classes");var g=(new dataTable()).table("feat");for(var z=e;z<=y;z++){c.feats.auto[z]=[];o=c.feats.auto[z];s=c.level[z].class_id;q=A.row(s);l=(new dataTable()).table(q.field("featstable"));var f=builder.classLevel(z,s);if(z==1&&c.background.feats.length){o.push(c.background.feats[0])}if(f==1&&q.field("hasdomains")==1){x=c.domain.length;while(x--){if(c.domain[x].id!=b.ID_NONE){w=c.domain[x].feats.length;while(w--){o.push(c.domain[x].feats[w])}}}}if(s==7&&f==2){t=this.get(b.FEAT_TYPE_COMBAT_STYLE,z);if(t.id!=b.ID_NONE){r=c.feats.rcs.id;o.push(t)}}var p,t,u,h;x=l.data.length;while(x--){p=l.row(false,x);if(p.field("grantedonlevel")==f){if(p.field("list")==3){h=p.field("grantedprereq",b.ID_NONE);if(h==3887&&r!=3887){continue}if(h==1730&&r!=1730){continue}if(h==1729&&r!=1729){continue}t=p.field("featindex");u=g.row(t).field("feat");if(u!=undefined){o.push({id:t,label:u,type:b.FEAT_TYPE_AUTO,category:g.row(t).field("featcategory")})}}}}var B=(new dataTable()).table("nwn2_deities");var n=q.field("favoredweaponproficiency");var v=q.field("favoredweaponfocus");var m=q.field("favoredweaponspecialization");if(n==f){t=B.row(c.deity.id).field("favoredweaponproficiency");o.push({id:t,label:g.row(t).field("feat"),type:b.FEAT_TYPE_AUTO,category:g.row(t).field("featcategory")})}if(v==f){t=B.row(c.deity.id).field("favoredweaponfocus");o.push({id:t,label:g.row(t).field("feat"),type:b.FEAT_TYPE_AUTO,category:g.row(t).field("featcategory")})}if(m==f){t=B.row(c.deity.id).field("favoredweaponspecialization");o.push({id:t,label:g.row(t).field("feat"),type:b.FEAT_TYPE_AUTO,category:g.row(t).field("featcategory")})}if(s==2&&f==1){if(c.domain[0].id==27||c.domain[1].id==27){t=B.row(c.deity.id).field("favoredweaponproficiency");o.push({id:t,label:g.row(t).field("feat"),type:b.FEAT_TYPE_AUTO,category:g.row(t).field("featcategory")});t=B.row(c.deity.id).field("favoredweaponfocus");o.push({id:t,label:g.row(t).field("feat"),type:b.FEAT_TYPE_AUTO,category:g.row(t).field("featcategory")})}}}return a.runScripts(b.SCRIPT_SUMMARY_AUTO_FEATS,c.feats.auto)}}})();builder.tick("Module: Spells");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.spell={}})();builder.tick("Module: Skills");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.skills={update:function(k){var e=a.max_level;var h=c.skills.length;for(var f=0;f<h;f++){c.skills[f].type=[];for(var g=1;g<=e;g++){c.skills[f].type[g]=this.skill_type(f,g)}}},validate:function(){var e=a.max_level;for(var f=1;f<=e;f++){if(build.skills.free(f)<0){return false}}return true},change:function(f,j){if(j===undefined){j=false}var g=(new dataTable()).table("skills").row(f);var m=[];var l=[];var n=a.max_level;var h=n;while(h--){m[h+1]=0;l[h+1]=0}if(f==-1||!g||!g.field("name")){var k=100;for(h=0;h<c.skills.length;h++){if(c.skills[h].id>100){k++}}k++;c.skills.push({id:k,icon:"ia_use",label:"Any Skill "+k,sort_label:"zAny Skill "+k,ability:false,points:m,type:l})}else{var e=true;for(h=0;h<c.skills.length;h++){if(c.skills[h].id==f){e=false;break}}if(e==true){c.skills.push({id:f,icon:g.field("icon"),label:g.field("name"),sort_label:g.field("name"),ability:g.field("keyability"),points:m,type:l})}}builder.log("skill","Added ["+f+"] "+g.field("name"));return(j==true)?true:build.changed()},sort:function(){c.skills.sort(function(f,e){if(f.sort_label===undefined){f.sort_label="Unknown"}if(e.sort_label===undefined){e.sort_label="Unknown"}var h=f.sort_label.toLowerCase();var g=e.sort_label.toLowerCase();if(h<g){return -1}if(h>g){return 1}return 0});build.changed()},fetch:function(){var k=[];var f=[];var h=[];var j=[];var g=c.skills.length;while(g--){j.push(c.skills[g].id)}var m=(new dataTable()).table("skills");var l=m.data.length;var n,e;for(var g=0;g<l;g++){n=m.row(false,g);e=n.field("a_id");if(n.field("removed")==1){continue}if(j.find(e)){f.push({id:e,icon:n.field("icon"),label:n.field("name"),hover:n.field("description")})}else{k.push({id:e,icon:n.field("icon"),label:n.field("name"),hover:n.field("description")})}}h.push({title:"Skills",feats:k,disabled:f});return{title:"Select Skill",categories:h,selected:[]}},total:function(h,g){var f=0;for(var e=1;e<=g;e++){f+=c.skills[h].points[e]}return f},increase:function(g,f){var e=this.free(f);if(e<=0){return false}if(this.cost(g,f)>e){return false}if(this.total(g,f)>=this.max(g,f)){return false}c.skills[g].points[f]++;this.reduceToMax(g);build.changed(f)},increaseMax:function(f,e,k,g){var m,n,l,h;var o=a.max_level;for(var j=1;j<=o;j++){c.skills[f].points[j]=0}for(var j=1;j<=e;j++){m=this.total(f,j);l=this.free(j);n=this.max(f,j);h=this.cost(f,j);if(k==true&&h>1){continue}while(l>=h&&m<n){c.skills[f].points[j]++;m++;l--}}if(g===undefined){build.changed(e)}},decrease:function(f,e){if(c.skills[f].points[e]<=0){return false}c.skills[f].points[e]--;build.changed(e)},decreaseMax:function(j,h,g){var e=a.max_level;for(var f=h;f<=e;f++){c.skills[j].points[f]=0}if(g===undefined){build.changed(h)}},reduceToMax:function(j){var h,e;var f=a.max_level;for(var g=f;g>0;g--){h=this.total(j,g);e=this.max(j,g);while(h>e&&c.skills[j].points[g]>0){c.skills[j].points[g]--;h--}}},unused:function(){var e=0;var f=a.max_level;for(var g=1;g<=f;g++){e+=(this.gain(g)-this.spent(g))}return e},gain:function(e){return d._cache[e].skill.gain},spent:function(h){var g=0;if(c.skills===undefined){return g}var f=c.skills.length;for(var e=0;e<f;e++){g+=(c.skills[e].points[h]*this.cost(e,h))}return g},fullspent:function(g){var f=0;for(var e=1;e<=g;e++){f+=this.spent(e)}return f},free:function(e){return(this.gain(e)-this.spent(e))+this.saved(e)},saved:function(f){var e=(f==1)?0:this.free(f-1);if(e>5){e=5}return(e>0)?e:0},max:function(f,e){switch(this.skill_type(f,e)){case b.SKILL_TYPE_NON_CLASS:return Math.floor((e+3)/2);case b.SKILL_TYPE_CROSS_CLASS:case b.SKILL_TYPE_CLASS:return(e+3)}},cost:function(f,e){switch(c.skills[f].type[e]){case b.SKILL_TYPE_CLASS:return 1;case b.SKILL_TYPE_NON_CLASS:case b.SKILL_TYPE_CROSS_CLASS:if(e==1){return 2}return(d.feats.have(a.featid_able_learner,(e-1)))?1:2}},skill_type:function(f,e){var o=(new dataTable()).table("classes");var p=o.row(c.level[e].class_id).field("skillstable");var l=(new dataTable()).table(p);var n=c.skills[f].id;if(n>100){return b.SKILL_TYPE_CLASS}var m=l.data.length;var q;for(var k=0;k<m;k++){q=l.row(false,k);if(q.field("skillindex")==n){if(q.field("classskill")==1){return b.SKILL_TYPE_CLASS}break}}var g=[];g[c.level[e].class_id]=false;var k=e;while(k-->1){l=(new dataTable()).table(o.row(c.level[k].class_id).field("skillstable"));m=l.data.length;for(var h=0;h<m;h++){q=l.row(false,h);if(q.field("skillindex")==n){if(q.field("classskill")==1){return b.SKILL_TYPE_CROSS_CLASS}break}}g[c.level[k].class_id]=false}return b.SKILL_TYPE_NON_CLASS}}})();builder.tick("Build Information");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;build.info={tags:false,initialise:function(){build.info._init=true;$(".selector.info .tabs .tab").each(function(e){$(this).bind("click",function(){build.info.tab(e)})});$("#tab_desc textarea,#tab_note textarea").ckeditor(function(){},builder.config.editor.generic);$("#tab_pros textarea,#tab_cons textarea").ckeditor(function(){},builder.config.editor.fake_li)},show:function(){var g=builder.build;if(build.info.tags==false){var j="";var h=builder.tags.length;var k,e;for(var f=0;f<h;f++){k=builder.tags[f].id;e=builder.tags[f].label;e=e.replace(/<a\b[^>]*>/i,"");e=e.replace(/<\/a>/i,"");j+='<label for="tag'+k+'"><input type="checkbox" data-id="'+k+'" id="tag'+k+'" name="tag[]" value="'+k+'"><span>'+e+"</span></label>"}j+='<div class="clearBoth"></div>';$(".tags_existing").html(j);build.info.tags=true}$(".tags_existing input").bind("change",function(){if($(this).attr("checked")=="checked"){$(this).parent().addClass("selected")}else{$(this).parent().removeClass("selected")}});$("#build_name").val(g.name);$("#tab_desc textarea").val(g.description);$("#tab_pros textarea").val(g.pros);$("#tab_cons textarea").val(g.cons);$("#tab_note textarea").val(g.notes);$("#new_tags").val(g.tags_custom);for(var f=0;f<g.tags.length;f++){$("#tag"+g.tags[f]).attr("checked","checked").parent().addClass("selected")}$(".selector.info").find(".dialog").css({top:$(window).height(),left:(($(window).width()/2)-350)}).end().show();$(".selector.info .dialog").animate({top:($(".selector.info").height()/2)-(300)},"fast",function(){$("#build_name").focus().select();$("body").bind("keyup",function(l){if(l.keyCode==27){$("body").unbind("keyup");build.info.close()}})});$("body").css("width",$("body").width()).css("overflow","hidden")},close:function(){$(".selector.info .dialog").animate({top:$(window).height()},"fast",function(){$(".selector.info").hide();$("body").css("overflow","").css("width","")})},apply:function(){c.name=$("#build_name").val();c.description=$("#tab_desc textarea").val();c.pros=$("#tab_pros textarea").val();c.cons=$("#tab_cons textarea").val();c.notes=$("#tab_note textarea").val();c.tags_custom=$("#new_tags").val();c.tags=[];var f=$(".tags_existing .selected input");for(var e=0;e<f.length;e++){c.tags.push($(f[e]).attr("data-id"))}build.hasChanged=true;$(".button.save").removeClass("disabled").find(".hover").html("<strong>Save Changes</strong> made to the build");this.close()},tab:function(e){$(".selector.info .tabs .tab").each(function(f){if(e==f){$(this).addClass("selected")}else{$(this).removeClass("selected")}});$("#tab_desc,#tab_note,#tab_pros,#tab_cons,#tab_tags").hide();switch(e){case 1:$("#tab_pros").show();CKEDITOR.instances.editor3.focus();break;case 2:$("#tab_cons").show();CKEDITOR.instances.editor4.focus();break;case 3:$("#tab_note").show();CKEDITOR.instances.editor2.focus();break;case 4:$("#tab_tags").show().find("textarea").focus();break;default:$("#tab_desc").show();CKEDITOR.instances.editor1.focus();break}},saveBuild:function(){if($(".button.save").hasClass("disabled")){return false}if(sliph.member==false){sliph.showMemberLogin();return}builder.events.save();build.hasChanged=false},exitBuilder:function(){var e=sliph.cookie.get("nwn2db_builder_exit",builder.directory.url);if(!build.hasChanged){sliph.cookie.clear("nwn2db_builder_exit");document.location=e;return false}sliph.message("Save Changes?","Do you want to save the changes before exiting?",[{label:"Save and Exit",callback:function(){sliph.closeMessage(function(){builder.events.save(true)})}},{label:"Just Exit",callback:function(){build.ignoreExitWarning=true;sliph.closeMessage();sliph.cookie.clear("nwn2db_builder_exit");document.location=e}},{label:"Cancel",bind:27,callback:function(){sliph.closeMessage()}}])}}})();builder.tick("Dialog: Abilities");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.selector.abilities={rendered:false,ability:[],points:false,hover:-1,render:function(){if(this.points===false){this.points=(0+a.ability_points)}var e="";for(var f=0;f<a.abilities.length;f++){e+='<tr onmouseover="builder.selector.abilities.hover('+f+');"><td>'+a.abilities[f].label+'</td><td><div class="value" id="selector_ability_value_'+f+'"></div><a class="minus" onclick="builder.selector.abilities.decrease('+f+');return false;"ondblclick="if(MSIE)builder.selector.abilities.decrease('+f+');return false;"></a><a class="plus" onclick="builder.selector.abilities.increase('+f+');return false;"ondblclick="if(MSIE)builder.selector.abilities.increase('+f+');return false;"></a></td><td id="selector_ability_mod_'+f+'"></td></tr>'}$("body").append('<div class="selector abilities"><div class="dialog"><div class="header"><span>Select Abilities</span><div class="close" onclick="builder.selector.abilities.close();"></div></div><div class="inner"><table><thead><tr><th>Ability</th><th class="ability_base">Base</th><th>Mod</th></tr></thead><tfoot><tr><td colspan="3"><a onclick="builder.selector.abilities.commit();">Update</a><a onclick="builder.selector.abilities.recommend();">Recommend</a><a onclick="builder.selector.abilities.close();">Cancel</a></td></tr></tfoot><tbody><tr><td colspan="3" id="selector_ability_points"></td></tr>'+e+'</tbody></table><div class="frame"><div class="content"></div></div></div><div class="swirl_bl"></div><div class="swirl_br"></div></div></div>');this.rendered=true},show:function(){if(!this.rendered){this.render()}$("body").bind("keyup",function(f){if(f.keyCode==27){$("body").unbind("keyup");builder.selector.abilities.close()}});this.ability=c.ability.id;this.refresh();$(".selector.abilities").show().find(".dialog").css({left:($("body").innerWidth()/2)-350,top:-500}).animate({top:50},"fast");$("body").css("width",$("body").width()).css("overflow","hidden")},close:function(){$(".selector.abilities .dialog").animate({top:-500},"fast",function(){$(".selector.abilities").hide();$("body").css("overflow","").css("width","")})},recommend:function(){var e=(new dataTable()).table("classes").row(c.level[1].class_id);this.ability[b.ABILITY_STR]=e.field("str");this.ability[b.ABILITY_DEX]=e.field("dex");this.ability[b.ABILITY_CON]=e.field("con");this.ability[b.ABILITY_INT]=e.field("int");this.ability[b.ABILITY_WIS]=e.field("wis");this.ability[b.ABILITY_CHA]=e.field("cha");this.points=0;this.refresh()},refresh:function(){var r=(new dataTable()).table("racialsubtypes").row(c.race.id);var f=this.ability[0]+r.field("stradjust",0);var p=this.ability[1]+r.field("dexadjust",0);var l=this.ability[2]+r.field("conadjust",0);var e=this.ability[3]+r.field("intadjust",0);var o=this.ability[4]+r.field("wisadjust",0);var m=this.ability[5]+r.field("chaadjust",0);var q=Math.floor((f-10)/2);var k=Math.floor((p-10)/2);var h=Math.floor((l-10)/2);var n=Math.floor((e-10)/2);var j=Math.floor((o-10)/2);var g=Math.floor((m-10)/2);$("#selector_ability_value_0").html(f);$("#selector_ability_value_1").html(p);$("#selector_ability_value_2").html(l);$("#selector_ability_value_3").html(e);$("#selector_ability_value_4").html(o);$("#selector_ability_value_5").html(m);$("#selector_ability_mod_0").html((q>=0)?"+"+q:q);$("#selector_ability_mod_1").html((k>=0)?"+"+k:k);$("#selector_ability_mod_2").html((h>=0)?"+"+h:h);$("#selector_ability_mod_3").html((n>=0)?"+"+n:n);$("#selector_ability_mod_4").html((j>=0)?"+"+j:j);$("#selector_ability_mod_5").html((g>=0)?"+"+g:g);$("#selector_ability_points").html((this._points==1)?"1 Point Remaining":this.points+" Points Remaining")},hover:function(e){if(e==this.hover){return}$(".selector.abilities .content").html((new dataTable()).table("iprp_abilities").row(e).field("description","Bad Strref"))},increase:function(f){if(this.ability[f]>=18){return}var e=Math.floor((this.ability[f]-10)/2);if(e<1){e=1}if(this.points-e<0){return false}this.points=this.points-e;this.ability[f]++;this.refresh()},decrease:function(f){if(this.ability[f]<=8){return}this.ability[f]--;var e=Math.floor((this.ability[f]-10)/2);if(e<1){e=1}this.points=this.points+e;this.refresh()},commit:function(){this.close();builder.processing("Updating Build",function(e){c.ability.id=e.ability;build.forceChange=true;build.changed()},{ability:this.ability})}}})();builder.tick("Dialog: Generic Selection");(function(){var b=builder.constant;var a=builder.rules;var d=builder.summary;var c=builder.build;builder.selector.generic={profile:{},hover:[],hover_store:[],selector:false,rendered:false,winData:false,open:function(j,l,k,g){if(!this.rendered){this.render()}this.selector=j;switch(j){case b.SELECTOR_SKILLS:this.generate(build.skills.fetch());break;case b.SELECTOR_DOMAIN:this.generate(build.domain.fetch(l,k));break;case b.SELECTOR_ANIMAL:this.generate(build.animal.fetch(l));break;case b.SELECTOR_FAMILIAR:this.generate(build.familiar.fetch(l));break;case b.SELECTOR_CLASS:this.generate(build.classes.fetch(l));break;case b.SELECTOR_SCHOOL:this.generate(build.school.fetch(l));break;case b.SELECTOR_RACE:this.generate(build.race.fetch());break;case b.SELECTOR_BACKGROUND:this.generate(build.background.fetch());break;case b.SELECTOR_ALIGNMENT:this.generate(build.alignment.fetch());break;case b.SELECTOR_DEITY:this.generate(build.deity.fetch());break;case b.SELECTOR_FEAT:this.generate(build.feat.fetch(l,k,g));break;case b.SELECTOR_COMBAT_STYLE:this.generate(build.feat.fetch(l,0,b.FEAT_TYPE_COMBAT_STYLE));break}$("body").bind("keyup",function(m){if(m.keyCode==27){$("body").unbind("keyup");builder.selector.generic.close()}});var f=this.winDim();var e=f[1]-(f[1]/4);var h=700;$(".selector.generic").find(".dialog").css("height",e).css("left",(f[0]/2)-(h/2)).css("top",(f[1]/2)-(e/2)).find(".inner").css("height",e-50).end().find(".frame").css("height",e-70).end().find(".content").html("<p>Hover over a list item to view more information.</p>").end().end().show().find(".search input").val("Search...").focus();$("body").css("width",$("body").width()).css("overflow","hidden")},select:function(e){if(b.CONFIG_DEBUG_FEATS==true){$("#ignore_feats").html($("#ignore_feats").html()+e+",");$("#featList_"+e).remove();return false}this.close();builder.processing("Updating Build",function(f){var g=f.id;switch(f.selector){case b.SELECTOR_SKILLS:build.skills.change(g);break;case b.SELECTOR_DOMAIN:build.domain.change(g);break;case b.SELECTOR_ANIMAL:build.animal.change(g);break;case b.SELECTOR_FAMILIAR:build.familiar.change(g);break;case b.SELECTOR_CLASS:build.classes.change(g);break;case b.SELECTOR_SCHOOL:build.school.change(g);break;case b.SELECTOR_RACE:build.race.change(g);break;case b.SELECTOR_BACKGROUND:build.background.change(g);break;case b.SELECTOR_ALIGNMENT:build.alignment.change(g);break;case b.SELECTOR_DEITY:build.deity.change(g);break;case b.SELECTOR_FEAT:build.feat.change(g);break;case b.SELECTOR_COMBAT_STYLE:build.feat.change(g);break}},{id:e,selector:this.selector})},close:function(){$("body").css("overflow","").css("width","");$(".selector.generic").hide()},hover:function(f,g,e){if(e!==undefined){g=(this.hover_store[g])?this.hover_store[g]:"&nbsp;"}if(this.hover[f]&&this.hover[f]==g){return}this.hover[f]=g;$(".selector.generic .content").html(g)},generate:function(r,p){if(p===undefined){this.winData=r}var m;var e;var f;var n="";var h="";$(".selector.generic .title").html(r.title);this.hover_store=[];var l=r.categories;var o=l.length;var f="";var k,g,q;for(k=0;k<o;k++){n+='<ul><li onclick="builder.selector.generic.collapse(event);"><span>'+l[k].title+"</span><ul>";m=l[k].feats;if(l[k].sort===undefined){m.sort(function(s,j){if(s.sort_label!==undefined){var u=s.sort_label.toLowerCase();var t=j.sort_label.toLowerCase()}else{var u=s.label.toLowerCase();var t=j.label.toLowerCase()}if(u<t){return -1}if(u>t){return 1}return 0})}e=m.length;for(g=0;g<e;g++){f=[];if(m[g].group!==undefined){if(r.selected.find(m[g].group_feats_id,true)){f.push("selected")}}else{if(r.selected.find(m[g].id)){f.push("selected")}}f=(f.length)?' class="'+f.join(" ")+'"':"";q=(m[g].group!==undefined)?"builder.selector.generic.showGroup("+k+","+g+","+0+")":"builder.selector.generic.select("+m[g].id+")";n+='<li id="featList_'+m[g].id+"\" onmouseover=\"builder.selector.generic.hover('selectionContent',"+this.hover_store.length+',1);" onclick="'+q+';"'+f+" style=\"background-image:url('"+builder.directory.icons+"30x30/"+m[g].icon+".png');\">"+m[g].label+"</li>";this.hover_store.push(m[g].hover)}m=l[k].disabled;if(l[k].sort===undefined){m.sort(function(s,j){if(s.sort_label!==undefined){var u=s.sort_label.toLowerCase();var t=j.sort_label.toLowerCase()}else{var u=s.label.toLowerCase();var t=j.label.toLowerCase()}if(u<t){return -1}if(u>t){return 1}return 0})}e=m.length;for(g=0;g<e;g++){f=["disabled"];if(r.selected.find(m[g].id)){f.push("selected")}f=(f.length)?' class="'+f.join(" ")+'"':"";q=(m[g].group!==undefined)?"builder.selector.generic.showGroup("+k+","+g+","+1+")":"builder.selector.generic.select("+m[g].id+")";n+='<li id="featList_'+m[g].id+"\" onmouseover=\"builder.selector.generic.hover('selectionContent',"+this.hover_store.length+',1);" onclick="'+q+';"'+f+" style=\"background-image:url('"+builder.directory.icons+"30x30/"+m[g].icon+".png');\">"+m[g].label+"</li>";this.hover_store.push(m[g].hover)}n+="</ul></li></ul>"}if(![b.SELECTOR_SKILLS,b.SELECTOR_CLASS,b.SELECTOR_RACE,b.SELECTOR_ALIGNMENT,b.SELECTOR_DEITY,b.SELECTOR_BACKGROUND].find(this.selector)){if(p===undefined){n='<ul><li><span>Special Actions</span><ul><li id="featList_-1" onmouseover="builder.selector.generic.hover(\'selectionContent\','+this.hover_store.length+',1);" onclick="builder.selector.generic.select(-1);" style="background-image:url(\''+builder.directory.icons+"30x30/ia_exit.png');\">Clear Selection</li></ul></li></ul>"+n;this.hover_store.push("Clear the selected feat")}else{n='<ul><li><span>Special Actions</span><ul><li id="featList_-1" onmouseover="builder.selector.generic.hover(\'selectionContent\','+this.hover_store.length+',1);" onclick="builder.selector.generic.showGroup(-1);" style="background-image:url(\''+builder.directory.icons+"30x30/ia_exit.png');\">Go Back</li></ul></li></ul>"+n;this.hover_store.push("Return to the normal feat selection list")}}if(this.selector==b.SELECTOR_SKILLS){n='<ul><li><span>Special Actions</span><ul><li id="featList_-1" onmouseover="builder.selector.generic.hover(\'selectionContent\','+this.hover_store.length+',1);" onclick="builder.selector.generic.select(-1);" style="background-image:url(\''+builder.directory.icons+"30x30/ia_use.png');\">Any Skill</li></ul></li></ul>"+n;this.hover_store.push("Select Any Skill")}$(".selector.generic ul").html(n);return true},winDim:function(){if(window.innerHeight){return[window.innerWidth,window.innerHeight]}return[document.documentElement.clientWidth,document.documentElement.clientHeight]},render:function(){$("body").append('<div class="selector generic"><div class="dialog">'+(b.CONFIG_DEBUG_FEATS==true?'<textarea id="ignore_feats" style="position:absolute;top:-100px;left:0;right:0" rows="5" cols="50"></textarea>':"")+'<div class="header"><span class="title">Select Feat</span><div class="close" onclick="builder.selector.generic.close();"></div></div><div class="inner"><ul><li>&nbsp;</li></ul><div class="frame"><div class="content"></div></div><div class="search"><input type="text" value=""onfocus="builder.selector.generic.search.focus();"onkeyup="builder.selector.generic.search.change();"></div></div><div class="swirl_bl"></div><div class="swirl_br"></div></div></div>');this.rendered=true},search:{focus:function(){$(".selector.generic .search input").select()},change:function(e){var f=$(".selector.generic .search input").val();if(f=="Search..."){return}f=f.toLowerCase();$(".selector.generic .inner ul li ul li").each(function(){var g=$(this).html().toLowerCase();if(f==""||g.indexOf(f)!=-1){$(this).show()}else{$(this).hide()}})}},showGroup:function(j,e,g){if(j===-1){this.generate(this.winData);return}var f=this.winData.categories[j].feats[e];var h={categories:[{disabled:[],feats:f.group_feats,id:b.ID_NONE,title:f.label}],selected:this.winData.selected,title:this.winData.title};this.generate(h,true)},collapse:function(e){if(e.target.tagName!="SPAN"){return false}var f=$(e.target).parents("li")[0];if($(f).hasClass("collapsed")){$(f).removeClass("collapsed")}else{$(f).addClass("collapsed")}}}})();

Engine.js
Hidden: show
// create the builder core object framework
var builderCore = function(){

// trigger the initialisation on DOM ready
$(function(){

// initialise the builder
builder.initialise();

});
};

// version information
builderCore.prototype.version = '2.0.9';
builderCore.prototype.version_raw = '209';

// are we doing a mass build import?
builderCore.prototype.importing = false;

// hover title tag storage
builderCore.prototype.titles = [];
// stores the timeout event so that it can be cancelled
builderCore.prototype.title_timeout = false;

// system debugging
builderCore.prototype.debug = false;

// directory references
builderCore.prototype.directory = {
base: false,
data: false,
css: false,
icons: false,
rules: false
};

// array of files waiting to be loaded and the callback function to
// execute once complete
builderCore.prototype.load_files = [];
builderCore.prototype.load_callback = false;
builderCore.prototype.load_addclass = '';
builderCore.prototype.load_addcount = 0;

// determines if this is the first time any file has been loaded
builderCore.prototype.load_init = false;

// dialog selector framework
builderCore.prototype.selector = {};

// builder configuration
builderCore.prototype.config = {

// extra feats can be displayed as either text or icons
feats_extra_display_type: 2, // default to text

// feat selector grouping
selector_group_feats: true
};

// total number of files loaded at initialisation
builderCore.prototype.loadCount = 82;
builderCore.prototype.loadedCount = 0;

/**
* tick
*
* performs an update of the progress bar
* @param string label label to show on the progress bar
* @return void
*/
builderCore.prototype.tick = function(label){

// update the progress label
$('#builder_processing').html('Loading ' + label).show();

// increment the load count
builder.loadedCount++;

// update the progress bar
$('#builder_progress div').css('width', (630 * (builder.loadedCount / (builder.loadCount + builder.load_addcount))) + 'px');
};

/**
* initialise
*
* Initialise the builder engine and load all required extensions
* @param void
* @return void
*/
builderCore.prototype.initialise = function(){

// make local references
var dirBase = this.directory.base;
var dirCSS = this.directory.css;
var dirURL = this.directory.url;

// prepare the loading bar
$('body').append('<div id="builder_progress"><div></div></div>');
$('#builder_progress').css({
left: ($(window).width() / 2) - 350,
bottom: 0,
position: 'fixed'
});
$('#builder_progress div').css('width', 0);

// initialisation started
this.log('builder', 'Initialisation Started');

if (this.debug == true){
// use the unpacked version
var files_add = 0;
var files = [

// load builder styles
{file: dirURL + 'assets/themes/default/ui.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'fonts.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'table_build.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'table_skills.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'table_abilities.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'table_stats.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'class_colours.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'selector_generic.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'selector_abilities.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'selector_info.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'validation.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'menus.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'general.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'summary.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'dialog.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'dialog_login.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'utilities.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'processing.css', label: 'Builder Theme', type: 'css'},
{file: dirCSS + 'skills.css', label: 'Builder Theme', type: 'css'},

// load core engine files
{file: dirBase + 'prototype.js', label: 'Prototype Extensions'},
{file: dirBase + 'constants.js', label: 'Builder Constants'},
{file: dirBase + 'data.js', label: '2DA Data Storage'},
{file: dirBase + 'output.js', label: 'Output Generator'},
{file: dirBase + 'rules.js', label: 'Game Rules'},
{file: dirBase + 'build.js', label: 'Build Outline'},
{file: dirBase + 'history.js', label: 'Undo History'},
{file: dirBase + 'events.js', label: 'Build Events'},
{file: dirBase + 'validator.js', label: 'Build Validator'},
{file: dirBase + 'ui.js', label: 'User Interface Enhancements'},

// load all summary extensions
{file: dirBase + 'summary/core.js', label: 'Build Summary'},
{file: dirBase + 'summary/output.js', label: 'Build Summary: Output'},
{file: dirBase + 'summary/feats.js', label: 'Build Summary: Feats'},
{file: dirBase + 'summary/saves.js', label: 'Build Summary: Saving Throws'},
{file: dirBase + 'summary/skills.js', label: 'Build Summary: Skills'},
{file: dirBase + 'summary/abilities.js', label: 'Build Summary: Abilities'},
{file: dirBase + 'summary/caster.js', label: 'Build Summary: Caster Progression'},
{file: dirBase + 'summary/spells.js', label: 'Build Summary: Spells'},
{file: dirBase + 'summary/bab.js', label: 'Build Summary: Base Attack Bonus'},
{file: dirBase + 'summary/classes.js', label: 'Build Summary: Classes'},
{file: dirBase + 'summary/hp.js', label: 'Build Summary: Hit Points'},
{file: dirBase + 'summary/armor.js', label: 'Build Summary: Armor'},
{file: dirBase + 'summary/attacks.js', label: 'Build Summary: Attacks'},
{file: dirBase + 'summary/reduction.js', label: 'Build Summary: Damage Reductions'},
{file: dirBase + 'summary/resistance.js', label: 'Build Summary: Resistances'},
{file: dirBase + 'summary/spell_dc.js', label: 'Build Summary: Spell DC'},
{file: dirBase + 'summary/xp_penalty.js', label: 'Build Summary: XP Penalty'},
{file: dirBase + 'summary/sneak_attack.js', label: 'Build Summary: Sneak Attack'},

// load builder menus
{file: dirBase + 'menus/core.js', label: 'Builder Menus'},
{file: dirBase + 'menus/feats.js', label: 'Builder Menus'},
{file: dirBase + 'menus/class.js', label: 'Builder Menus'},
{file: dirBase + 'menus/skills.js', label: 'Builder Menus'},

// load output formats
{file: dirBase + 'output/build_table.js', label: 'Output Generators'},
{file: dirBase + 'output/skills_table.js', label: 'Output Generators'},
{file: dirBase + 'output/stats_frame.js', label: 'Output Generators'},
{file: dirBase + 'output/abilities_table.js', label: 'Output Generators'},
{file: dirBase + 'output/utilities_bar.js', label: 'Build Utilities'},
{file: dirBase + 'output/build_info.js', label: 'Build Information'},

// load build modules
{file: dirBase + 'modules/class.js', label: 'Module: Classes'},
{file: dirBase + 'modules/ability.js', label: 'Module: Abilities'},
{file: dirBase + 'modules/background.js', label: 'Module: Backgrounds'},
{file: dirBase + 'modules/race.js', label: 'Module: Racial Types'},
{file: dirBase + 'modules/alignment.js', label: 'Module: Alignments'},
{file: dirBase + 'modules/deity.js', label: 'Module: Deities'},
{file: dirBase + 'modules/domain.js', label: 'Module: Cleric Domains'},
{file: dirBase + 'modules/school.js', label: 'Module: Spell Schools'},
{file: dirBase + 'modules/animal.js', label: 'Module: Animal Companions'},
{file: dirBase + 'modules/familiar.js', label: 'Module: Familiars'},
{file: dirBase + 'modules/feat.js', label: 'Module: Feats'},
{file: dirBase + 'modules/spell.js', label: 'Module: Spells'},
{file: dirBase + 'modules/skills.js', label: 'Module: Skills'},
{file: dirBase + 'modules/info.js', label: 'Build Information'},

// load selector dialogs
{file: dirBase + 'selectors/abilities.js', label: 'Dialog: Abilities'},
{file: dirBase + 'selectors/generic.js', label: 'Dialog: Generic Selection'},

// load WYSIWYG Editor files
{file: dirURL + 'assets/sliph/ui/editor.css', label: 'Builder WYSIWYG Editor', type: 'css'},
{file: dirURL + 'assets/sliph/editor/ckeditor/ckeditor.js', label: 'Builder WYSIWYG Editor'},
{file: dirURL + 'assets/sliph/editor/ckeditor/adapters/jquery.js', label: 'Builder WYSIWYG Editor'},
{file: dirBase + 'editor-config.js', label: 'Builder WYSIWYG Editor'}

];
}
else {
// use the packed version
var files_add = 55;
var files = [
{file: dirCSS + 'pack.builder.css', label: 'Builder Theme', type: 'css'},
{file: dirBase + 'pack.builder.js', label: 'Builder Engine'},
// load WYSIWYG Editor files
{file: dirURL + 'assets/sliph/ui/editor.css', label: 'Builder WYSIWYG Editor', type: 'css'},
{file: dirURL + 'assets/sliph/editor/ckeditor/ckeditor.js', label: 'Builder WYSIWYG Editor'},
{file: dirURL + 'assets/sliph/editor/ckeditor/adapters/jquery.js', label: 'Builder WYSIWYG Editor'},
{file: dirBase + 'editor-config.js', label: 'Builder WYSIWYG Editor'}
];
}

// load the builder core extensions
this.load(files, function(){

// fetch the build tags
builder.events.fetchTags();

// initialisation complete
builder.log('builder', 'Initialisation Complete', 1);

// Load the ruleset
builder.rules.loadSet(builder.game_version, function(){

// change the default rules max level to whatever was supplied via the
// new builder dialog - we only want to do this if there is no build
// set to autoload
if (builder.autoload == 0){
builder.rules.max_level = builder.max_level;
}

// re-initialise all engine extensions
builder.output.initialise();
builder.ui.initialise();
builder.summary.initialise();
build.initialise();

// check if we are auto-loading a build
if (builder.autoload != 0) builder.events.load(builder.autoload);

// trigger the automatic UI updating
builder.output.pause = false;

// initialise the history buttons and labels
builder.history.initialise();

// remove the loading cover screen
$('#builder_loading').hide();

// remove the loading progress indicator
$('#builder_progress').remove();

// Convert all title attributes
builder.makeTitles();

// Reset the hasChanged flag
build.hasChanged = false;
});
}, files_add);
};

/**
* log
*
* logging wrapper function
* @param string scope log scope
* @param string text log text
* @param boolean separate add a separater line after output?
* @return false
*/
builderCore.prototype.log = function(scope, text, separate) {

// check for a mass import
if (builder.importing == true) return;

// abort if we are not in debugging mode
if (!this.debug) return false;

// abort if there is no console object found
if (typeof console == 'undefined') return false;

// pad the scope text
while (scope.length < 10) scope += ' ';

// output to the console
console.log(scope.toUpperCase() + text);

// check for a separater line
if (separate) console.log('----------------------------------------');

return false;
};

/**
* load
*
* Loads a builder entension
* @param array extensions extension files to load
* @param function callback callback function once file loaded
* @param string addClass add a specific class to the SCRIPT tags?
* @param integer filesAdd add X number to the total count
* @return void
*/
builderCore.prototype.load = function(extensions, callback, addClass, filesAdd){

// store the information
this.load_files = extensions;
this.load_callback = callback;
this.load_addclass = (addClass == undefined) ? '' : addClass;
this.load_addcount = (filesAdd === undefined) ? 0 : filesAdd;

// check if this is the first time any file has been loaded
if (!this.load_init) {

// create the loader progress meter
$('#container').append('<div id="builder_processing">Loading Builder Extension Files...</div>');
this.load_init = true;

} else {

$('builder_processing').show();
}

// start the loop
this._loadNext();
};

/**
* _loadNext
*
* Looped function to load all pending files
* @param void
* @return void
*/
builderCore.prototype._loadNext = function(){

// check if there are no more files to load
if (!builder.load_files.length) {

// remove the progress div
$('#builder_processing').hide();

// execute the callback function
builder.load_callback();

// stop further execution
return;
}

// find the next file to load
var next = builder.load_files[0];

// log the load attempt
//builder.log('load', next.label + ' (' + next.file + ')');

// determine if we are loading a css file
if (next.type !== undefined && next.type == 'css'){

var type = 'css';

// compose the new style element
var script = document.createElement("link");

// Assign the file path and type attribute
script.setAttribute("href", next.file + '?' + builder.version_raw);
script.setAttribute("rel", "stylesheet");
script.setAttribute("type", "text/css");
script.setAttribute("media", "screen");
if (builder.load_addclass != ''){
script.setAttribute("class", builder.load_addclass);
}

} else {

var type = 'js';

// compose the new script element
var script = document.createElement("script");

// Assign the file path and type attribute
script.setAttribute("src", next.file + '?' + builder.version_raw);
script.setAttribute("type", "text/javascript");
if (builder.load_addclass != ''){
script.setAttribute("class", builder.load_addclass);
}

// update the progress label
$('#builder_processing').html('Loading ' + next.label).show();

// apply the callback function
if ($.browser.msie !== undefined &&
$.browser.version == "8.0"){

var callback_ie = function(source){
if (this.readyState == 'complete' || this.readyState == 'loaded') builder._loadNext();
};

// apply for IE
script.onreadystatechange = callback_ie;
}

// apply for web browsers
script.onload = builder._loadNext;
}

// append the script element to the <head> tag
document.getElementsByTagName('head')[0].appendChild(script);

// remove the loaded file from the array
builder.load_files.shift();

// increment the load count
builder.loadedCount++;

// update the progress bar
$('#builder_progress div').css('width', (630 * (builder.loadedCount / (builder.loadCount + builder.load_addcount))) + 'px');

// if this was a css file, skip the waiting for file load as it doesn't work
if (type == 'css') builder._loadNext();
};

/**
* processing
*
* shows the processing gif and performs an action
* @param string label label to display
* @param function script function script to execute
* @param object params script params
* @return void
*/
builderCore.prototype.processing = function(label, script, params){

// update the notifier
$('#builder_processing').html(label).show();

// execute the script
script(params);

// hide the updater
$('#builder_processing').hide();
};

/**
* makeTitles
*
* converts all title="" attributes to a new hover state
* @param void
* @return void
*/
builderCore.prototype.makeTitles = function(){

var $b = this;

// make sure the hover element has been created
if (!$('#title_hover').length){
// create the title hover element
$('body').append('<div id="title_hover"></div>');

$('body').bind('mousemove', function(event){

$b._pageX = event.pageX;
$b._pageY = event.pageY;
$b._centerTitle(event);
});
}

// find all elements that have a title attribute
$('#content').find('[title]').each(function(index){

// fetch the title
var title = $(this).attr('title');

// check for a feat conversion title
if (title.substring(0,5) == 'feat:'){
// store the title tag
var feat = title.substring(5);
var $feat = (new dataTable()).table('feat').row(feat);
var icon = $b.directory.icons + '30x30/' + $feat.field('icon') + '.png';
title =
'<div class="title">' +
'<span style="background-image:url('+icon+');"></span>' +
$feat.field('feat') +
'</div>' +
$feat.field('description');
}

// check for a skill conversion title
if (title.substring(0,6) == 'skill:'){
var skill = title.substring(6);
// is this an any skill?
if (parseInt(skill) > 100){
// store the title tag
title =
'<div class="title">' +
'<span style="background-image:url('+$b.directory.icons + '30x30/ia_use.png);"></span>Any Skill' +
'</div>';
}
else {
// store the title tag
var $skill = (new dataTable()).table('skills').row(skill);
var icon = $b.directory.icons + '30x30/' + $skill.field('icon') + '.png';
title =
'<div class="title">' +
'<span style="background-image:url('+icon+');"></span>' +
$skill.field('name') +
'</div>' +
$skill.field('description');
}
}

// remove the title tag
$(this).removeAttr('title');

// set the hover state
$(this).bind('mouseover', function(event, ui){

event.stopPropagation();

// clear the timeout
clearTimeout($b.title_timeout);

// set a new timeout
$b.title_timeout = setTimeout(function(){

// don't show the hover title in a system message is being shown
if ($('#builder_message').length) return;

// check that it wasn't triggered from a validation element
if ($(event.target).hasClass('validation')) return false;

// update the content
$('#title_hover').html(title).width('auto');

// make sure the element hasn't reched the maximum width
if ($('#title_hover').width() > $b._title.width) {
$('#title_hover').width($b._title.width);
}

// show the element
$('#title_hover').show();
$b._centerTitle(window.event);

}, $b._title.interval);

}).bind('mouseout', function(){

// clear the timeout
clearTimeout($b.title_timeout);

// hide the hover element
$('#title_hover').hide();
});
});
};

builderCore.prototype._pageX = 0;
builderCore.prototype._pageY = 0;
builderCore.prototype._title = {
interval: 600,
width: 250,
left: 5,
top: 25
};
/**
* _centerTitle
*
* centers the title hover element on the current mouse position
* @param void
* @return void
*/
builderCore.prototype._centerTitle = function(){

var left = this._pageX + this._title.left;
var top = this._pageY + this._title.top;

// check boundaries
if ((left - window.scrollX) + (this._title.width + 10) > $(window).width()){
left = $(window).width() - (this._title.width + 10);
}
if ((top - window.scrollY) + this._title.top + $('#title_hover').height() > $(window).height()){
top = top - (this._title.top * 2) - $('#title_hover').height();
}

$('#title_hover').css({ left: left, top: top });
};

/**
* changeScope
*
* changes the current build scope
* @param integer scope scope to change to
* @return void
*/
builderCore.prototype.changeScope = function(scope){

// make local references for speed benefits
var $C = builder.constant; // builder constants

// change the scope
build.scope = scope;
$('#output_utilities .toggle').removeClass('on');

switch (scope){

case $C.SCOPE_BUILD:
$('#table_skills').hide();
$('#table_spells').hide();
$('#table_build').show();
$('#output_utilities .build').addClass('on');
$('#output_utilities .undo,#output_utilities .redo').show();
break;

case $C.SCOPE_SKILLS:
$('#table_skills').show();
$('#table_spells').hide();
$('#table_build').hide();
$('#output_utilities .skills').addClass('on');
$('#output_utilities .undo,#output_utilities .redo').hide();
break;

case $C.SCOPE_SPELLS:
$('#table_skills').hide();
$('#table_spells').show();
$('#table_build').hide();
$('#output_utilities .spells').addClass('on');
$('#output_utilities .undo,#output_utilities .redo').hide();
break;
}

// re-bind all keys
//builder.ui.bindKeys();

// trigger an update
builder.output.update();
};

/**
* restartValidate
*
* validates the build after an engine restart to make sure all data is valid
* @param void
* @return void
*/
builderCore.prototype.restartValidate = function(previousGameVersion){

// make local references for speed benefits
var $C = builder.constant; // builder constants
var $R = builder.rules; // builder rules object
var $S = builder.summary; // builder summary object
var $B = builder.build; // core build data

if (previousGameVersion === undefined) previousGameVersion = 'oc';

// define data tables
var table_races = (new dataTable()).table('racialsubtypes');
var table_classes = (new dataTable()).table('classes');
var table_feats = (new dataTable()).table('feat');
var table_deity = (new dataTable()).table('nwn2_deities');
var table_backgrounds = (new dataTable()).table('backgrounds');
var table_familiars = (new dataTable()).table('hen_familiar');
var table_animals = (new dataTable()).table('hen_companion');
var table_domains = (new dataTable()).table('domains');

// define variables
var max_level = $R.max_level;
var row, class_id, alt_class = 0, label;
var checked = {};
var notify = [];
var notified = {};
var i;

// check for invalid classes
// loop through all levels...
for (i = 1; i <= max_level; i++){

// extract the class id
class_id = $B.level.class_id;

// have we already checked this class id?
if (checked[class_id] !== undefined) continue;

// check if the class is still valid
row = table_classes.row(class_id);
if (row.rowValid == false){

// find the alternate class
switch (class_id) {
case 55: alt_class = 3; break; // Spirit Shaman > Druid
case 58: alt_class = 2; break; // Favored Soul > Cleric
case 61: alt_class = 39; break; // Hellfire Warlock > Warlock
case 60: alt_class = 51; break; // Doomguide > Warpriest
case 53: alt_class = 10; break; // Red Wizard > Wizard
case 56: alt_class = 51; break; // Stormlord > Warpriest
case 59: alt_class = 8; break; // Swashbuckler > Rogue
case 54: alt_class = 9; break; // Arcane Scholar > Sorceror
default: alt_class = 0; // other
}
// check if we need to add the notification
if (notified[class_id] === undefined){
// get the new class label
label = table_classes.row(alt_class).field('name');
notified[class_id] = 1;
notify.push('Changed <strong>'+$B.level.class_label+'</strong> to <strong>'+label+'</strong>');
}
// change the class
build.classes.level = i;
build.classes.change(alt_class, 1, true);

} else {

// register the check
checked[class_id] = 1;
}
}

// check for invalid race
row = table_races.row($B.race.id);
if (row.rowValid == false){
// change race to Human
build.race.change(17, true);
notify.push('Changed race to <strong>Human</strong>');
}

// check for invalid deity
row = table_deity.row($B.deity.id);
if (row.rowValid == false){
// change deity to None
build.deity.change(0, true);
notify.push('Changed deity to <strong>No Deity</strong>');
}

// check for invalid background
row = table_backgrounds.row($B.background.id);
if (row.rowValid == false){
// change deity to None
build.background.change(0, true);
notify.push('Changed background to <strong>No Background</strong>');
}

// check for invalid domains
for (i = 0; i < $B.domain.length; i++){
// skip invalid indicies
if ($B.domain === undefined) continue;
// check if the domain is still valid
if ($B.domain.id == $C.ID_NONE) continue;
row = table_domains.row($B.domain.id);
if (row.rowValid == false){
// change domain to None
notify.push('Removed <strong>'+$B.domain.label+'</strong> domain');
build.domain.change($C.ID_NONE, i, true);
}
}

// check for invalid familiars
for (var i = 0; i < $B.familiar.length; i++){
// skip invalid indicies
if ($B.familiar === undefined) continue;
// check if the familiar is still valid
row = table_familiars.row($B.familiar.id);
if (row.rowValid == false){
// change familiar to None
notify.push('Removed <strong>'+$B.familiar[i].label+'</strong> familiar');
build.familiar.level = $B.familiar[i].level;
build.familiar.change($C.ID_NONE, true);
}
}

// check for invalid animal companions
for (var i = 0; i < $B.animal.length; i++){
// skip invalid indicies
if ($B.animal[i] === undefined) continue;
// check if the animal is still valid
row = table_animals.row($B.animal[i].id);
if (row.rowValid == false){
// change animal to None
notify.push('Removed <strong>'+$B.animal[i].label+'</strong> animal companion');
build.animal.level = $B.animal[i].level;
build.animal.change($C.ID_NONE, true);
}
}

// check for invalid feats
for (var l = 1; l <= $R.max_level; l++){
// - normal
for (i in $B.feats.normal[l]){
// skip invalid indicies
if ($B.feats.normal[l][i] === undefined) continue;
// check if the feat is still valid
row = table_feats.row($B.feats.normal[l][i].id);
if (row.rowValid == false){
// remove feat
notify.push('Removed <strong>'+$B.feats.normal[l][i].label+'</strong> feat');
build.feat.level = l;
build.feat.slot = i;
build.feat.type = $C.FEAT_TYPE_NORMAL;
build.feat.change($C.ID_NONE, true);
}
}
// - bonus
for (i in $B.feats.bonus[l]){
// skip invalid indicies
if ($B.feats.bonus[l][i] === undefined) continue;
// check if the feat is still valid
row = table_feats.row($B.feats.bonus[l][i].id);
if (row.rowValid == false){
// remove feat
notify.push('Removed <strong>'+$B.feats.bonus[l][i].label+'</strong> feat');
build.feat.level = l;
build.feat.slot = i;
build.feat.type = $C.FEAT_TYPE_BONUS;
build.feat.change($C.ID_NONE, true);
}
}
// - sub-select
for (i in $B.feats.subselect[l]){
// skip invalid indicies
if ($B.feats.subselect[l][i] === undefined) continue;
// check if the feat is still valid
row = table_feats.row($B.feats.subselect[l][i].id);
if (row.rowValid == false){
// remove feat
notify.push('Removed <strong>'+$B.feats.subselect[l][i].label+'</strong> feat');
build.feat.level = l;
build.feat.slot = i;
build.feat.type = $C.FEAT_TYPE_SUBSELECT;
build.feat.change($C.ID_NONE, true);
}
}
// - quick to master
if ($B.feats.qtm.id !== undefined && $B.feats.qtm.id !== $C.ID_NONE){
// check if the feat is still valid
row = table_feats.row($B.feats.qtm.id);
if (row.rowValid == false){
// remove feat
notify.push('Removed <strong>'+$B.feats.qtm.label+'</strong> feat');
build.feat.level = 1;
build.feat.slot = 0;
build.feat.type = $C.FEAT_TYPE_QUICK_TO_MASTER;
build.feat.change($C.ID_NONE, true);
}
}
}

// return the notifications
return notify;
};

/**
* classLevel
*
* Calculates the total number of levels taken in a class for the target level
* @param integer level level to calculate to
* @param integer id class id to calculate
* @return integer
*/
builderCore.prototype.classLevel = function(level, id){

// make local references for speed benefits
var $B = builder.build; // core build data

// initialise the counts
var total = 0;

// find all matching levels
while (level > 0) {
if (level > 0 && $B.level[level].class_id == id) total++;
level--;
}

// return the total
return total;
};

// create the usable instance
var builder = new builderCore();

Editor Config.js
Hidden: show
/*******************************************************************************
* CKEDITOR CONFIGURATION FOR SLIPH CMS
******************************************************************************/

builder.config.editor = {

generic: {
language: 'en',
skin: 'office2003',
resize_enabled: false,
toolbarCanCollapse: false,
autoParagraph: false,
scayt_autoStartup: true,
forcePasteAsPlainText: true,
height: '260px',
removePlugins: 'font,save,elementspath,scayt',
contentsCss: builder.directory.css + 'editor.css',
toolbar: [
['Bold','Italic','Underline','Strike','-','Undo','Redo','-','Link','Unlink','-','NumberedList','BulletedList','-','HorizontalRule']
],
removeFormatTags: 'b,big,code,del,dfn,div,font,i,ins,kbd,q,samp,small,span,strike,sub,sup,tt,u,var'
},

fake_li: {
bodyId: 'fake_li',
language: 'en',
skin: 'office2003',
resize_enabled: false,
toolbarCanCollapse: false,
autoParagraph: false,
scayt_autoStartup: true,
forcePasteAsPlainText: true,
height: '260px',
removePlugins: 'font,save,elementspath,scayt',
contentsCss: builder.directory.css + 'editor.css',
toolbar: [
['Bold','Italic','Underline','Strike','-','Undo','Redo','-','Link','Unlink']
],
removeFormatTags: 'b,big,code,del,dfn,div,font,i,ins,kbd,q,samp,small,span,strike,sub,sup,tt,u,var'
}
}

CKEDITOR.on('instanceReady', function(ev) {
ev.editor.dataProcessor.writer.selfClosingEnd = '>';
ev.editor.dataProcessor.writer.setRules('p',{ breakAfterOpen : false });
ev.editor.dataProcessor.writer.setRules('li',{ breakAfterOpen : false });
ev.editor.dataProcessor.htmlFilter.addRules({
elements :{
a : function(element){
if (!element.attributes.rel) element.attributes.rel = 'nofollow';
}
}
});
});

x1_scripts.js
Hidden: show
(function(){

// make local references for speed benefits
var $C = builder.constant; // builder constants
var $R = builder.rules; // builder rules object
var $S = builder.summary; // builder summary object
var $B = builder.build; // core build data


// ----------------------------
// Ruleset : Mask of the Betrayer
// Version : 1.0.0
// ----------------------------

/*******************************************************************************
* Perfect 2WF
*
* Used to copy the Main Hand attack scores to the Off-hand for simplicity
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_ATTACK,
'Perfect 2WF Clone',
function(data){

// check if we have the "P2WF" feat or the Ranger Combat Style equivilant
if ($S.feats.have(1972) == true || $S.feats.have(1973) == true){

// log the script
builder.log('SCRIPT', 'Executing Game Script: "'+this.label+'"');

// copy the values from the main-hand to the off-hand
data.melee.dual_off = data.melee.dual_main;
}

// return the modified data object
return data;
}
);

})();

Kaedrin Scripts.js
Hidden: show
(function(){

// make local references for speed benefits
var $C = builder.constant; // builder constants
var $R = builder.rules; // builder rules object
var $S = builder.summary; // builder summary object
var $B = builder.build; // core build data


// ----------------------------
// Ruleset : Kaedrin's Class Pack
// Version : 1.42c
// ----------------------------

if (builder.data !== undefined){

// Hexblade - change it's "spellcaster" flag to 1
builder.data._store.classes.d[119][18] = 1;
// and it's "hasarcane" to 1
builder.data._store.classes.d[119][21] = 1;
// we also want to adjust it's caster level by -3

// change the Dragon Disciple Colour feats to be non-history category
// v1.42c - Updated Feat ID's
builder.data._store.feat.d[2132][43] = 'classability_ft_cat';
builder.data._store.feat.d[2133][43] = 'classability_ft_cat';
builder.data._store.feat.d[2134][43] = 'classability_ft_cat';
builder.data._store.feat.d[2135][43] = 'classability_ft_cat';
builder.data._store.feat.d[2136][43] = 'classability_ft_cat';
builder.data._store.feat.d[2137][43] = 'classability_ft_cat';
builder.data._store.feat.d[2138][43] = 'classability_ft_cat';
builder.data._store.feat.d[2139][43] = 'classability_ft_cat';
builder.data._store.feat.d[2140][43] = 'classability_ft_cat';
builder.data._store.feat.d[2141][43] = 'classability_ft_cat';
builder.data._store.feat.d[2142][43] = 'classability_ft_cat';
}

/*******************************************************************************
* Hexblade -3 caster level script
* v1.41.4
*
* Used to adjust the Hexblade class caster level by -3 to match to the class
* definitions. It's easier to make it a script rather than hack the 2DA
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_CASTER,
'Hexblade Caster Level',
function(data){

// check if we have the hexblade class in the arcane list
if (data.arcane.classes[185] !== undefined){

$classes = data.arcane.classes;

// reduce the effects and value
$classes[185].effects[0][1] -= 3;
$classes[185].value -= 3;

// now check if this is no longer the highest value
var high = 0, index = $C.ID_NONE;
var i = $classes.length;
while (i--){
if ($classes[i] === undefined) continue;
if ($classes[i].value > high){
// update the high value
high = $classes[i].value;
index = i;
}
}

// update the actual value
data.arcane.high = high;
data.arcane.index = index;
}

// return the modified data object
return data;
}
);

/*******************************************************************************
* Bardic Music Stacking
* v1.41.4
*
* Used to manipulate the Bardic Music auto-feats to merge levels of Lyric Tham,
* Stormsinger, Canaith Lyrist and Dissonant Chord
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_AUTO_FEATS,
'Bardic Music',
function(data){

// make local references for speed benefits
var $B = builder.build; // core build data

// make a reference to the feats table
var $feat = (new dataTable()).table('feat');

// prepare the order of feats list
var feats_order = [-1,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373];
var feats_index = -1;

// loop through each level
var max_level = $R.max_level, i, j, feat;
for (i = 1; i <= max_level; i++){

if ([125,109,124,184,1].find($B.level[i].class_id)){
// increment the feats index
feats_index++;
// make sure the index is still valied
if (feats_order[feats_index] === undefined){
// can't do anything more, end here
return data;
}
// add the feat to this level if there is a valid index
feat = feats_order[feats_index];
// check if the feat id is valid
if (feat == -1) continue;
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
return data;
}
);

/*******************************************************************************
* Wild Shape Stacking
* v1.41.4
*
* Used to manipulate the Wild Shape auto-feats to merge levels of Druid
* Daggerspell Shaper, Lion of Talisid and Natures Warrior
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_AUTO_FEATS,
'Wild Shape',
function(data){

// make local references for speed benefits
var $B = builder.build; // core build data

// make a reference to the feats table
var $feat = (new dataTable()).table('feat');

// prepare the order of feats list
var feats_ws = [305,335,336,337,338,339,1931,1932,1933,3756,3757,3758,3759,3760,3761,3762];
var feats_es = [304,340,341,342,3763,3764,3765,3766,3767,3768];
// define the levels we would gain the Wild/Elemental Shape feats on
var level_gain_ws = [0,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1];
var level_gain_es = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1];

var feats_index_ws = -1;
var feats_index_es = -1;

var level_total = 0;
var level_value = 0;

// loop through each level
var max_level = $R.max_level, i, j, feat;
for (i = 1; i <= max_level; i++){

if ([148,123,121,3].find($B.level[i].class_id)){
// increment the level total
level_total++;
level_value = level_total;
// if this is a lion of tal level, subtract 2 from the level
if ($B.level[i].class_id == 123) level_value -= 2;
// do we need to add special feats?
if (level_value == 12){
// add the Plant Wild Shape
if (data[i] === undefined) data[i] = [];
data[i].push({
id: 2111,
label: $feat.row(2111).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
// check if we would gain a wild shape ability on this level
if (level_gain_ws[level_value] !== undefined &&
level_gain_ws[level_value] == 1){

// add the wild shape feat progression

// increment the feats index
feats_index_ws++;
// make sure the index is still valied
if (feats_ws[feats_index_ws] !== undefined){
// add the feat to this level if there is a valid index
feat = feats_ws[feats_index_ws];
// check if the feat id is valid
if (feat == -1) continue;
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
// check if we would gain an elemental shape ability on this level
if (level_gain_es[level_value] !== undefined &&
level_gain_es[level_value] == 1){

// add the elemental shape feat progression

// increment the feats index
feats_index_es++;
// make sure the index is still valied
if (feats_es[feats_index_es] !== undefined){
// add the feat to this level if there is a valid index
feat = feats_es[feats_index_es];
// check if the feat id is valid
if (feat == -1) continue;
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
// if this is the daggershaper class
if ($B.level[i].class_id == 148){

// add the extra wild shape uses
if ([1,4,7,10].find($B.level[i].class_level)){

// add the extra feat

// increment the feats index
feats_index_ws++;
// make sure the index is still valied
if (feats_ws[feats_index_ws] !== undefined){
// add the feat to this level if there is a valid index
feat = feats_ws[feats_index_ws];
// check if the feat id is valid
if (feat == -1) continue;
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
}
}
}
return data;
}
);

/*******************************************************************************
* Swashbucklers Grace Stacking
* v1.41.4
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_AUTO_FEATS,
'Swashbuckler Grace',
function(data){

// we need to test each feat on each level to see if we have the required one

// loop through each level
var max_level = $R.max_level, i, j, feat, have_feat = false;
for (i = 1; i <= max_level; i++){
// loop through each feat - normal
for (j in $B.feats.normal[i]){
if ($B.feats.normal[i][j].id == 3319){
have_feat = true;
break;
}
}
if (have_feat) break;
}
if (!have_feat) return data;

// make a reference to the feats table
var $feat = (new dataTable()).table('feat');

// prepare the order of feats list
var feats = [2137,2138,2139,2140];
var feats_index = -1;
var feats_dodge = [2143,2144,2145,2146,2147,2148];
var feats_index_dodge = -1;
var level_total = 0;

// loop through each level
for (i = 1; i <= max_level; i++){
if ([8,144,59].find($B.level[i].class_id)){
// increment the level total
level_total++;
// check if we would gain a feat on this level
if ([2,11,20,29].find(level_total)){
// increment the feats index
feats_index++;
// make sure the index is still valied
if (feats[feats_index] !== undefined){
// add the feat to this level if there is a valid index
feat = feats[feats_index];
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
// - Swash Dodge
// check if we would gain a feat on this level
if ([5,10,15,20,25,30].find(level_total)){
// increment the feats index
feats_index_dodge++;
// make sure the index is still valied
if (feats_dodge[feats_index_dodge] !== undefined){
// add the feat to this level if there is a valid index
feat = feats_dodge[feats_index_dodge];
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
}
}
return data;
}
);

/*******************************************************************************
* Sneak Attack Stacking - Swift Ambusher
* v1.41.4
*
* Used to manipulate the Sneak Attack auto-feats to merge levels of Scout and Rogue
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_AUTO_FEATS,
'Swift Ambusher',
function(data){

// we need to test each feat on each level to see if we have the required one

// loop through each level
var max_level = $R.max_level, i, j, feat, have_feat = false;
for (i = 1; i <= max_level; i++){
// loop through each feat - normal
for (j in $B.feats.normal[i]){
if ($B.feats.normal[i][j].id == 3710){
have_feat = true;
break;
}
}
if (have_feat) break;
}
if (!have_feat) return data;

// make a reference to the feats table
var $feat = (new dataTable()).table('feat');

// prepare the order of feats list
var feats = [221,345,346,347,348,349,350,351,352,353,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041];
var feats_index = -1;
var level_total = 0;

// loop through each level
for (i = 1; i <= max_level; i++){
if ([149,8].find($B.level[i].class_id)){
// increment the level total
level_total++;
// check if we would gain a feat on this level
if ([1,3,5,7,9,11,13,15,17,19,21,23,25,27,29].find(level_total)){
// increment the feats index
feats_index++;
// make sure the index is still valied
if (feats[feats_index] !== undefined){
// add the feat to this level if there is a valid index
feat = feats[feats_index];
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
}
}
return data;
}
);

/*******************************************************************************
* Sneak Attack Stacking - Swift Hunter
* v1.41.4
*
* Used to manipulate the Sneak Attack auto-feats to merge levels of Scout and Ranger
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_AUTO_FEATS,
'Swift Ambusher',
function(data){

// we need to test each feat on each level to see if we have the required one

// loop through each level
var max_level = $R.max_level, i, j, feat, have_feat = false;
for (i = 1; i <= max_level; i++){
// loop through each feat - normal
for (j in $B.feats.normal[i]){
if ($B.feats.normal[i][j].id == 3711){
have_feat = true;
break;
}
}
if (have_feat) break;
}
if (!have_feat) return data;

// make a reference to the feats table
var $feat = (new dataTable()).table('feat');

// prepare the order of feats list
var feats = [221,345,346,347,348,349,350,351,352,353,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041];
var feats_index = -1;
var level_total = 0;

// loop through each level
for (i = 1; i <= max_level; i++){
if ([149,7].find($B.level[i].class_id)){
// increment the level total
level_total++;
// check if we would gain a feat on this level
if ([1,3,5,7,9,11,13,15,17,19,21,23,25,27,29].find(level_total)){
// increment the feats index
feats_index++;
// make sure the index is still valied
if (feats[feats_index] !== undefined){
// add the feat to this level if there is a valid index
feat = feats[feats_index];
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
}
}
return data;
}
);

/*******************************************************************************
* Sneak Attack Stacking - Daring Outlaw
* v1.41.4
*
* Used to manipulate the Sneak Attack auto-feats to merge levels of Scout Rogue
* and Ninja
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_AUTO_FEATS,
'Daring Outlaw - SAD',
function(data){

// we need to test each feat on each level to see if we have the required one

// loop through each level
var max_level = $R.max_level, i, j, feat, have_feat = false;
for (i = 1; i <= max_level; i++){
// loop through each feat - normal
for (j in $B.feats.normal[i]){
if ($B.feats.normal[i][j].id == 3319){
have_feat = true;
break;
}
}
if (have_feat) break;
}
if (!have_feat) return data;

// make a reference to the feats table
var $feat = (new dataTable()).table('feat');

// prepare the order of feats list
var feats = [221,345,346,347,348,349,350,351,352,353,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041];
var feats_index = -1;
var level_total = 0;

// loop through each level
for (i = 1; i <= max_level; i++){
if ([8,144,59].find($B.level[i].class_id)){
// increment the level total
level_total++;
// check if we would gain a feat on this level
if ([1,3,5,7,9,11,13,15,17,19,21,23,25,27,29].find(level_total)){
// increment the feats index
feats_index++;
// make sure the index is still valied
if (feats[feats_index] !== undefined){
// add the feat to this level if there is a valid index
feat = feats[feats_index];
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
}
}
return data;
}
);

/*******************************************************************************
* Eldritch Blast Progression
* v1.42c
*
* Used to manipulate the Warlock Elritch Blast auto-feats to merge levels of
* Mystic Knights, Dragonslayer and Heartwarder
******************************************************************************/
$R.addScript(
$C.SCRIPT_SUMMARY_AUTO_FEATS,
'Eldritch Blast',
function(data){

// make local references for speed benefits
var $B = builder.build; // core build data

// make a reference to the feats table
var $feat = (new dataTable()).table('feat');

// prepare the order of feats list
var feats_order = [1411,1412,1413,1414,1415,1416,1417,1418,1419,1948,1949,1950,1951,1952];
var feats_index = -1;
// define the levels we would gain the feats on
var level_gain = [-1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1];
var level_total = 0;

// add the Warlock base class and Eldritch Disciple class (no feat check required)
var class_ids = [39,117];
var $subselect = $B.feats.subselect;
// each class needs to have the Warlock Progression feat to allow progression
// check Mystic Knight
if ($subselect[132] !== undefined &&
$subselect[132][1] !== undefined &&
$subselect[132][1][0] !== undefined &&
$subselect[132][1][0].id == 3341)
// Add class levels
class_ids.push(132);
// check Heartwarder
if ($subselect[131] !== undefined &&
$subselect[131][1] !== undefined &&
$subselect[131][1][0] !== undefined &&
$subselect[131][1][0].id == 3271)
// Add class levels
class_ids.push(131);
// check Dragonslayer
if ($subselect[134] !== undefined &&
$subselect[134][1] !== undefined &&
$subselect[134][1][0] !== undefined &&
$subselect[134][1][0].id == 3372)
// Add class levels
class_ids.push(134);
// check Stormsinger
if ($subselect[109] !== undefined &&
$subselect[109][1] !== undefined &&
$subselect[109][1][0] !== undefined &&
$subselect[109][1][0].id == 3545)
// Add class levels
class_ids.push(109);
// check Child of Night
if ($subselect[140] !== undefined &&
$subselect[140][1] !== undefined &&
$subselect[140][1][0] !== undefined &&
$subselect[140][1][0].id == 3585)
// Add class levels
class_ids.push(140);
// check Daggerspell Mage
if ($subselect[147] !== undefined &&
$subselect[147][1] !== undefined &&
$subselect[147][1][0] !== undefined &&
$subselect[147][1][0].id == 3718)
// Add class levels
class_ids.push(147);

// loop through each level
var max_level = $R.max_level, i, j, feat;
for (i = 1; i <= max_level; i++){

if (class_ids.find($B.level[i].class_id)){
// determine what class this is
switch ($B.level[i].class_id){

case 140:
case 147:
// Child of Night, Daggerspell Mage
// - doesn't progress on 2nd level
if ($B.level[i].class_level == 2) continue;
break;

case 134:
// Dragonslayer - only progress on odd levels
if ((parseInt($B.level[i].class_level) % 2) == 0) continue;
break;

default:
// normal progression
// Warlock, Heartwarder, Mystic Night, Stormsinger
}
// increment the level total
level_total++;
// check if we would gain a feat on this level
if (level_gain[level_total] !== undefined && level_gain[level_total] == 1){

// increment the feats index
feats_index++;
// make sure the index is still valid
if (feats_order[feats_index] === undefined){
// can't do anything more, end here
return data;
}
// add the feat to this level if there is a valid index
feat = feats_order[feats_index];
// check if the feat id is valid
if (feat == -1) continue;
// add the feat
if (data[i] === undefined) data[i] = [];
data[i].push({
id: feat,
label: $feat.row(feat).field('feat'),
type: $C.FEAT_TYPE_AUTO,
category: 'classability_ft_cat'
});
}
}
}
return data;
}
);

})();

Kaedrin Feats
Hidden: show
(function(){

// make local references for speed benefits
var $C = builder.constant; // builder constants
var $R = builder.rules; // builder rules object
var $S = builder.summary; // builder summary object

// --- Racial Traits ---
// Long Gait

// --- Background Traits ---

// --- Familiar Class Abilities ---

// --- Class Abilities ---
// Template Saves
$R.feat[3889] = {save:[
{type: $C.SAVING_THROW_FORT, progression: {classes: [154],levels: [2,4,6,8,10],values: [+1,+2,+3,+4,+5]}},
{type: $C.SAVING_THROW_WILL, progression: {classes: [154],levels: [2,4,6,8,10],values: [+1,+2,+3,+4,+5]}}
]};

$R.feat[3551] = {resist: [{type: $C.RESIST_TYPE_SPELL, value: +12, per_level: 1}]};
$R.feat[3541] = {armor: [{type: $C.ARMOR_TYPE_DODGE, ability: $C.ABILITY_CON}]};
$R.feat[3606] = {armor: [{type: $C.ARMOR_TYPE_DODGE, progression: {classes: [143], levels: [1,5,9], values: [+1,+2,+3]}}]};
$R.feat[3616] = {
armor: [
{ type: $C.ARMOR_TYPE_AC,
lowest: [{
type: $C.CONDITION_ABILITY,
value: $C.ABILITY_WIS
},{
type: $C.CONDITION_CLASS_LEVEL,
value: 144
}],
restrict_armor: $C.ARMOR_NONE
},
{ type: $C.ARMOR_TYPE_DODGE,
progression: {
classes: [144],
levels: [5,10,15,20,25,30],
values: [+1,+2,+3,+4,+5,+6],
if_feat:{
id: 3696,
classes: [4,116]
}
},
restrict_armor: $C.ARMOR_NONE
}
],
ignore: [260], // ignore the Monk AC bonus
};
$R.feat[3227] = {attack_mod: [{
apply: $C.WEAPON_HAND_RANGED,
value: 0,
progression: {classes:[118], levels:[2,4], values:[+1,+2]}
}]};
$R.feat[3090] = {
skill: [{type: $C.SKILL_HIDE, value: +2},
{type: $C.SKILL_MOVE, value: +2},
{type: $C.SKILL_TUMBLE, value: +2}]
};
$R.feat[3706] = {save:[
{type: $C.SAVING_THROW_FORT, progression: {classes: [149],levels: [2,11,20,29],values: [+1,+2,+3,+4]}},
{type: $C.SAVING_THROW_REFL, progression: {classes: [149],levels: [2,11,20,29],values: [+1,+2,+3,+4]}},
{type: $C.SAVING_THROW_WILL, progression: {classes: [149],levels: [2,11,20,29],values: [+1,+2,+3,+4]}}
]};
// duplicate feat?
$R.feat[3732] = $R.feat[3706];
$R.feat[3261] = {skill:[
{type: $C.SKILL_DIPLOMACY, value: +2},
{type: $C.SKILL_SEARCH, value: +2}
]};
$R.feat[3589] = {
skill:[{type: $C.SKILL_HIDE, class_level: [140]}],
resist:[
{type: $C.RESIST_TYPE_POISON, progression: {classes: [140],levels: [6],values: [$C.RESIST_IMMUNE]}},
{type: $C.RESIST_TYPE_DISEASE, progression: {classes: [140],levels: [6],values: [$C.RESIST_IMMUNE]}}
]
};
$R.feat[3648] = {
skill: [{
type: $C.SKILL_TUMBLE,
progression: {
classes: [144],
levels: [6,12,18,24,30],
values: [+2,+4,+6,+8,+10]
}
}]
};
$R.feat[3789] = {
save: [{
type: $C.SAVING_THROW_FORT,
lowest: [{type: $C.CONDITION_ABILITY, value: $C.ABILITY_CHARISMA, minimum: 1},
{type: $C.CONDITION_CLASS_LEVEL, value: 185}]
},{
type: $C.SAVING_THROW_REFL,
lowest: [{type: $C.CONDITION_ABILITY, value: $C.ABILITY_CHARISMA, minimum: 1},
{type: $C.CONDITION_CLASS_LEVEL, value: 185}]
},{
type: $C.SAVING_THROW_WILL,
lowest: [{type: $C.CONDITION_ABILITY, value: $C.ABILITY_CHARISMA, minimum: 1},
{type: $C.CONDITION_CLASS_LEVEL, value: 185}]
}],
ignore: [473]
};
$R.feat[3284] = {
armor: [{
type: $C.ARMOR_TYPE_NATURAL,
progression: {
classes: [122],
levels: [01,04,07,10],
values: [+1,+2,+3,+4]
}
}]
};
$R.feat[3255] = {
armor: [{
type: $C.ARMOR_TYPE_NATURAL,
lowest: [{
type: $C.CONDITION_CLASS_LEVEL,
value: 121
}]
}]
};
$R.feat[3107] = {
skill: [
{type: $C.SKILL_HIDE,progression: {classes: [166],levels: [2,4],values: [+2,+4]}},
{type: $C.SKILL_MOVE,progression: {classes: [166],levels: [2,4],values: [+2,+4]}},
{type: $C.SKILL_TUMBLE,progression: {classes: [166],levels: [2,4],values: [+2,+4]}}
]
};
$R.feat[3115] = {
armor: [{
type: $C.ARMOR_TYPE_DODGE,
restrict_armor: ($C.ARMOR_LIGHT | $C.ARMOR_NONE),
lowest: [{type: $C.CONDITION_ABILITY,value: $C.ABILITY_INT},
{type: $C.CONDITION_CLASS_LEVEL,value: 108}]
}]
};
$R.feat[3547] = {attack: +1};
$R.feat[3590] = {
resist: [{
type: $C.RESIST_TYPE_COLD,
progression: {classes: [140], levels: [1,5,9], values: [5,10,15]}
}]
};
$R.feat[3514] = {
attack_mod: [{
apply: $C.WEAPON_HAND_ANY,
progression: {classes:[181],levels:[4,10],values:[+1,+2]}
}]
};
$R.feat[3360] = {
damage_reduction: {
overcome: $C.REDUCTION_NONE,
progression: {classes:[134],levels:[3,6,9],values:[+1,+2,+3]}
}
};
$R.feat[3352] = {
skill: [
{type: $C.SKILL_SEARCH,progression: {classes: [133],levels: [2,5,8],values: [+2,+4,+6]}}
]
};
$R.feat[3300] = {
resist: [{type: $C.RESIST_TYPE_PARALYSIS,value: $C.RESIST_IMMUNE},
{type: $C.RESIST_TYPE_FEAR,value: $C.RESIST_IMMUNE},
{type: $C.RESIST_TYPE_SLEEP,value: $C.RESIST_IMMUNE}]
};


// --- Teamwork Feats ---

// --- General Feats ---
// Expert Tactition
$R.feat[1095] = {attack:+1};
$R.feat[3523] = {attack_mod:[{apply: $C.WEAPON_HAND_MAIN, value: +1}],
armor:[{type:$C.ARMOR_TYPE_DODGE, value:+1}]};
$R.feat[3209] = {attack_mod:[{apply: $C.WEAPON_HAND_DUAL, value:+2}]};
$R.feat[3134] = {attack_mod:[{apply: $C.WEAPON_HAND_RANGED, value:+2}]};
$R.feat[3524] = {attack_mod:[{apply: $C.WEAPON_HAND_DUAL, value:+2}]};
$R.feat[3525] = {attack_mod:[{apply: $C.WEAPON_HAND_DUAL, value:+2}], ignore: [3524]};
$R.feat[3526] = {attack_mod:[{apply: $C.WEAPON_HAND_DUAL, value:+2}], ignore: [3524,3525]};
$R.feat[3198] = {damage_reduction: {overcome:$C.REDUCTION_NONE,value:+3,stack:$C.STACK_NONE}};
$R.feat[3199] = {damage_reduction: {overcome:$C.REDUCTION_NONE,value:+5,stack:$C.STACK_NONE}};
$R.feat[3206] = {attack:+2};
$R.feat[3534] = {
armor: [{type: $C.ARMOR_TYPE_DODGE, value: +1}],
skill: [{type: $C.SKILL_HIDE, value: +1},
{type: $C.SKILL_MOVE, value: +1},
{type: $C.SKILL_TUMBLE, value: +1}]
};
$R.feat[3535] = {
armor: [{type: $C.ARMOR_TYPE_DODGE, value: +2}],
skill: [{type: $C.SKILL_HIDE, value: +2},
{type: $C.SKILL_MOVE, value: +2},
{type: $C.SKILL_TUMBLE, value: +2}],
ignore: [3534]
};
$R.feat[3886] = {
armor: [{type: $C.ARMOR_TYPE_DODGE, value: +3}],
skill: [{type: $C.SKILL_HIDE, value: +3},
{type: $C.SKILL_MOVE, value: +3},
{type: $C.SKILL_TUMBLE, value: +3}],
ignore: [3534,3535]
};
$R.feat[3194] = {armor: [{type: $C.ARMOR_TYPE_SHIELD, value: +3}], ignore: [1117,1102]};
$R.feat[3204] = {attack_mod:[{apply: $C.WEAPON_HAND_DUAL, value: +2}]};
// Dragon Colours
$R.feat[3249] = {
resist: [{
type_by_feat: [
{feat: [3238,3243,3242], type: $C.RESIST_TYPE_ACID},
{feat: [3239,3241], type: $C.RESIST_TYPE_ELECTRICAL},
{feat: [3247,3246], type: $C.RESIST_TYPE_COLD},
{feat: [3245,3240,3243], type: $C.RESIST_TYPE_FIRE}
],
value: $C.RESIST_IMMUNE
}]
};
$R.feat[3258] = {
damage_reduction: {
overcome: $C.REDUCTION_NONE,
value: +3
}
};
$R.feat[3500] = {resist: [{type: $C.RESIST_TYPE_ELECTRICAL, value: +10}]};
$R.feat[3501] = {resist: [{type: $C.RESIST_TYPE_ACID, value: +10}]};
$R.feat[3502] = {resist: [{type: $C.RESIST_TYPE_FIRE, value: +10}]};
$R.feat[3503] = {resist: [{type: $C.RESIST_TYPE_COLD, value: +10}]};
$R.feat[3359] = {
resist: [
{type: $C.RESIST_TYPE_ACID, progression: {classes:[134],levels:[5,10],values:[+5,+10]}},
{type: $C.RESIST_TYPE_COLD, progression: {classes:[134],levels:[5,10],values:[+5,+10]}},
{type: $C.RESIST_TYPE_ELECTRICAL, progression: {classes:[134],levels:[5,10],values:[+5,+10]}},
{type: $C.RESIST_TYPE_FIRE, progression: {classes:[134],levels:[5,10],values:[+5,+10]}},
{type: $C.RESIST_TYPE_SONIC, progression: {classes:[134],levels:[5,10],values:[+5,+10]}}
]
};
$R.feat[3515] = {armor: [{type:$C.ARMOR_TYPE_DODGE, value:+1}]};
$R.feat[3685] = {
skill: [{
type: $C.SKILL_DIPLOMACY,
progression: {classes:[146],levels:[2,6,10],values:[+2,+4,+6]}
}]
};
$R.feat[3272] = {
skill: [
{type: $C.SKILL_BLUFF, value: +2},
{type: $C.SKILL_DIPLOMACY, value: +2},
{type: $C.SKILL_INTIMIDATE, value: +2},
{type: $C.SKILL_PERFORM, value: +2},
{type: $C.SKILL_USE_MAGIC, value: +2}
]
};
$R.feat[3287] = {
resist: [
{type: $C.RESIST_TYPE_FEAR, progression:{classes:[127],levels:[3],values:[$C.RESIST_IMMUNE]}},
{type: $C.RESIST_TYPE_DISEASE, progression:{classes:[127],levels:[4],values:[$C.RESIST_IMMUNE]}},
{type: $C.RESIST_TYPE_PARALYSIS, progression:{classes:[127],levels:[7],values:[$C.RESIST_IMMUNE]}},
{type: $C.RESIST_TYPE_ABILITY_DRAIN, progression:{classes:[127],levels:[8],values:[$C.RESIST_IMMUNE]}},
{type: $C.RESIST_TYPE_ENERGY_DRAIN, progression:{classes:[127],levels:[10],values:[$C.RESIST_IMMUNE]}}
]
};
$R.feat[3273] = {
resist: [
{type:$C.RESIST_TYPE_CHARM, value:$C.RESIST_IMMUNE},
{type:$C.RESIST_TYPE_DOMINATE, value:$C.RESIST_IMMUNE}
]
};
$R.feat[3596] = {resist:[{type:$C.RESIST_TYPE_FEAR,value:$C.RESIST_IMMUNE}]};
$R.feat[3154] = {save: [{type:$C.SAVING_THROW_MIND,value:+4}]};
$R.feat[3790] = {
save:[
{type:$C.SAVING_THROW_FORT,value:+4},
{type:$C.SAVING_THROW_WILL,value:+4}
]
};
$R.feat[3301] = {
armor: [{
type: $C.ARMOR_TYPE_NATURAL,
progression: {classes:[135],levels:[7,12,17],values:[+1,+2,+3]}
}]
};
$R.feat[3085] = {
save: [
{type:$C.SAVING_THROW_TRAPS,progression:{
classes:[129],
levels:[1,4,7,10],
values:[+1,+2,+3,+4]
}}
],
skill: [
{type:$C.SKILL_DISABLE, progression:{classes:[129],levels:[2,8],values:[+2,+4]}},
{type:$C.SKILL_OPEN, progression:{classes:[129],levels:[2,8],values:[+2,+4]}},
{type:$C.SKILL_HIDE, progression:{classes:[129],levels:[2,8],values:[+2,+4]}},
{type:$C.SKILL_MOVE, progression:{classes:[129],levels:[2,8],values:[+2,+4]}},
{type:$C.SKILL_SEARCH, progression:{classes:[129],levels:[2,8],values:[+2,+4]}},
{type:$C.SKILL_TUMBLE, progression:{classes:[129],levels:[2,8],values:[+2,+4]}}
]
};
$R.feat[3219] = {
armor: [{type:$C.ARMOR_TYPE_NATURAL,progression:{
classes:[114],
levels:[3,5,7],
values:[+3,+5,+7]
}}]
};
$R.feat[3221] = {
resist: [
{type:$C.RESIST_TYPE_MIND, value:$C.RESIST_IMMUNE},
{type:$C.RESIST_TYPE_POISON, value:$C.RESIST_IMMUNE},
{type:$C.RESIST_TYPE_SLEEP, value:$C.RESIST_IMMUNE},
{type:$C.RESIST_TYPE_PARALYSIS, value:$C.RESIST_IMMUNE},
{type:$C.RESIST_TYPE_STUN, value:$C.RESIST_IMMUNE},
{type:$C.RESIST_TYPE_CRITICAL, value:$C.RESIST_IMMUNE},
{type:$C.RESIST_TYPE_SNEAK, value:$C.RESIST_IMMUNE}
]
};
$R.feat[3286] = {
resist: [{type:$C.RESIST_TYPE_COLD,value:$C.RESIST_IMMUNE}]
};
$R.feat[3111] = {resist: [{type: $C.RESIST_TYPE_SPELL, value: +10, class_level: 107}]};
$R.feat[3146] = {resist: [{type: $C.RESIST_TYPE_SPELL, value: +10, per_level: +1}]};
$R.feat[3548] = {save: [{type:$C.SAVING_THROW_MIND, value:+2}]};
$R.feat[3143] = {resist: [{type:$C.RESIST_TYPE_ELECTRICAL,progression:{classes:[109],levels:[4,6,8],values:[5,10,15]}}]};
$R.feat[3595] = {
resist: [{
type_by_feat: [
{feat: [3238,3242,3244], type: $C.RESIST_TYPE_ACID},
{feat: [3239,3241], type: $C.RESIST_TYPE_ELECTRICAL},
{feat: [3247,3246], type: $C.RESIST_TYPE_COLD},
{feat: [3245,3240,3243], type: $C.RESIST_TYPE_FIRE}
],
progression:{
classes:[139],
levels:[1,5,7,10],
values:[+5,+10,+15,+20]
}
}]
};
$R.feat[3083] = {
save: [
{type:$C.SAVING_THROW_FORT, progression:{classes:[119],levels:[1,4],values:[+1,+2]}},
{type:$C.SAVING_THROW_REFL, progression:{classes:[119],levels:[1,4],values:[+1,+2]}},
{type:$C.SAVING_THROW_WILL, progression:{classes:[119],levels:[1,4],values:[+1,+2]}}
]
};
$R.feat[3110] = {damage_reduction:{overcome: $C.REDUCTION_NONE,value: +3}};
$R.feat[3565] = {
armor:[
{type: $C.ARMOR_TYPE_DODGE, progression:{
classes:[138],
levels:[13,17,21],
values:[+2,+4,+6]
}}
]
};
$R.feat[3709] = {
armor:[
{type: $C.ARMOR_TYPE_DODGE, progression:{
classes:[149],
levels:[3,7,11,15,19,23,27],
values:[+1,+2,+3,+4,+5,+6,+7]
}}
]
};
$R.feat[3142] = {skill:[{type:$C.SKILL_PERFORM,value:+2}]};
$R.feat[3292] = {
armor:[{type:$C.ARMOR_TYPE_DODGE,progression:{classes:[126],levels:[3,6,9],values:[+1,+2,+3]}}]
};
$R.feat[3163] = {
attack_mod: [{
apply:$C.WEAPON_HAND_ANY,
progression:{classes:[113],levels:[1,7],values:[+1,+2]}
}],
armor:[{
type:$C.ARMOR_TYPE_DODGE,
progression:{classes:[113],levels:[1,7],values:[+1,+2]}
}],
save: [{
type:$C.SAVING_THROW_REFL,
progression:{classes:[113],levels:[1,7],values:[+1,+2]}
}]
};
$R.feat[3055] = {
attack_mod:[{
apply:$C.WEAPON_HAND_ANY,
progression:{classes:[110],levels:[2,4],values:[+1,+2]}
}],
armor:[{
type:$C.ARMOR_TYPE_DODGE,
progression:{classes:[110],levels:[1,3,5],values:[+1,+2,+3]}
}]
};
$R.feat[3145] = {
damage_reduction:{
overcome: $C.REDUCTION_NONE,
value: +3
}
};
$R.feat[3771] = {
armor: [{type:$C.ARMOR_TYPE_DODGE,value:+1}],
attack_mod: [{
apply: $C.WEAPON_HAND_ANY,
progression: {classes:[141],levels:[3],values:[+1]}
}]
};
$R.feat[3770] = {
caster: {
class_id: 10,
use_feat_label: 1,
progression: {classes:[141],levels:[3,4,5],values:[+1,+2,+3]}
}
};
$R.feat[3057] = {resist: [{type:$C.RESIST_TYPE_FEAR,value:$C.RESIST_IMMUNE}]};

// --- Spellcasting ---
$R.feat[3150] = {spell_dc: [{school: $C.SCHOOL_INVOKER, value: +2}]};
$R.feat[3532] = {spell_dc: [{school: $C.SCHOOL_INVOKER, value: +2}]};
$R.feat[3531] = {spell_dc: [{school: $C.SCHOOL_INVOKER, value: +2}], ignore: [3532]};
$R.feat[3850] = {spell_dc: [{school: $C.SCHOOL_INVOKER, value: +2}]};
$R.feat[3529] = {skill: [{type:$C.SKILL_PERFORM, value:+2}]};

// SPECIAL FEAT - Protective Ward
$R.feat[3553] = {
script: function(level, feat_type){

// fetch the classes
var $classes = $S.classes.fetch(level, feat_type);

// check if there is only ranger
if ($classes.order.length == 1 && $classes.order[0].id == 7){

// return the Ranger only version
return {
attack_mod: [{
apply: $C.WEAPON_HAND_ANY,
progression: {
classes: [7],
levels: [4,24],
values: [+1,+2]
}
}],
armor: [{
type: $C.ARMOR_TYPE_DODGE,
progression: {
classes: [7],
levels: [4,24],
values: [+2,+4]
}
}]
};
}
else {

// return the default
return {
armor: [{
type: $C.ARMOR_TYPE_DODGE,
progression: {
classes: [7],
levels: [4,24],
values: [+1,+2]
}
}]
};
}
}
};

// SPECIAL FEAT - Melodic Casting
$R.feat[3330] = {
script: function(level, feat_type){

// make local references for speed benefits
var $C = builder.constant; // builder constants
var $B = builder.build; // core build data

// fetch the skills the hard way
var concentration = 0;
var perform = 0;
var max_level = $R.max_level;
var x = $B.skills.length; while (x--){
if ($B.skills[x].id == $C.SKILL_CONCENTRATION){
// loop through each level
for (var y = 1; y <= max_level; y++){
concentration += parseInt($B.skills[x].points[y]);
}
}
if ($B.skills[x].id == $C.SKILL_PERFORM){
// loop through each level
for (var y = 1; y <= max_level; y++){
perform += parseInt($B.skills[x].points[y]);
}
}
}
// calculate the difference between the two values
var diff = (perform - concentration);
if (diff > 0){
return {
skill: [{type: $C.SKILL_CONCENTRATION, value: diff}]
};
}
else {
// no point!
return false;
}
}
};
$R.feat[3751] = {
attack_mod: [{
apply: $C.WEAPON_HAND_ANY,
value: +1
}]
};

// --- Skill and Save ---
$R.feat[3130] = {skill: [{type: $C.SKILL_DIPLOMACY, value: +2}]};

// --- Practiced Spellcaster
$R.feat[3856] = {caster: {class_id: 185, levels: +4}}; // Hex Blade
$R.feat[3753] = {caster: {class_id: 39, levels: +4}}; // Invoker
$R.feat[3353] = {caster: {class_id: 30, levels: +4}}; // Assassin
$R.feat[3355] = {caster: {class_id: 142, levels: +4}}; // Avenger
$R.feat[3354] = {caster: {class_id: 31, levels: +4}}; // Blackguard

// --- Heritage Feats ---

// --- Background ---

// --- Spell Focus ---

// --- Epic Feats ---

})();
Eclypticon
Posts: 1009
Joined: Mon May 30, 2011 7:26 pm
Location: USA

Re: We Need a Character Builder

Unread post by Eclypticon »

OMG. Look at that JS.
Post Reply

Return to “Solved Problems”