chargen.System.Class = {
  initClass : function(name, p) {
    p = p.prototype;
    p.id = name;
    var initFFP = chargen.System.Commons.initFFP;
    if (!p.book)  p.book   = 'phb';
    if (!p.updateMisc)     p.updateMisc = chargen.System.Class.miscUpdator;
    if (!p.updateSkills)   p.updateSkills = chargen.System.Class.skillsUpdator;
    if (!p.updateFeatures) p.updateFeatures = chargen.System.featureUpdator;
    if (!p.updatePowers)   p.updatePowers = chargen.System.powerUpdator;
    if (!p.updateFeats)    p.updateFeats = chargen.System.featUpdator;
    if (!p.updateProfs) p.updateProfs = chargen.System.Class.profUpdator;
    if (!p.class_skills) p.class_skills   = [];
    if (!p.skills)     p.skills    = {};
    if (!p.atwill)     p.atwill   = [];    else initFFP('power', p, 'atwill');
    if (!p.encounter)  p.encounter  = [];  else initFFP('power', p, 'encounter');
    if (!p.daily)      p.daily    = [];    else initFFP('power', p, 'fedailyatures');
    if (!p.utility)    p.utility  = [];    else initFFP('power', p, 'utility');
    if (!p.auto_feats) p.auto_feats = [];  else initFFP('feat', p, 'auto_feats');
    if (!p.features)   p.features = [];    else initFFP('feature', p, 'features');
    if (!p.powers)     p.powers   = [];    else initFFP('power', p, 'powers');
    if (!p.feats)      p.feats    = [];    else initFFP('feat', p, 'feats');
    if (!p.keywords)   p.keywords = [p.id.toLowerCase(), p.type, p.power]; else p.keywords.push(p.id.toLowerCase());
    if (p.dynamic_features) initFFP('feature', p, 'dynamic_features');
  },

  initClass2 : function(p) {
    p = p.prototype;
    var initFFP = chargen.System.Commons.initFFP;
  //  if (p.dynamic_features)
  },

  // Keyword updater for heroic classes
  miscUpdator : function(chr) {
    chr.keywords = chr.keywords.concat(this.keywords);
  },

  // Class armour & weapon proficiency updator
  profUpdator : function(chr) {
    for each (let prof in this.armour)
      chr.armour[prof] = chargen.LIST.MANDATORY;
    for each (let prof in this.proficiencies)
      chr.proficiencies[prof] = chargen.LIST.MANDATORY;
  },

  // Skill updater for heroic classes
  skillsUpdator : function(chr) {
    if (this.class_skills)
       for each (let skill in this.class_skills)
         if (!chr.trainedSkills[skill] || chr.trainedSkills[skill] < chargen.LIST.AVAILABLE)
           chr.trainedSkills[skill] = chargen.LIST.AVAILABLE;
    if (this.auto_skills)
       for each (let skill in this.auto_skills)
         if (!chr.trainedSkills[skill] || chr.trainedSkills[skill] < chargen.LIST.MANDATORY)
           chr.trainedSkills[skill] = chargen.LIST.MANDATORY;
    for (let [skill, trained] in Iterator(this.skills))
       if (trained)
         if (!chr.trainedSkills[skill] || chr.trainedSkills[skill] < chargen.LIST.SELECTED)
           chr.trainedSkills[skill] = chargen.LIST.SELECTED;
  }
};



let (cls = chargen.Classes) {


cls.Cleric = function() {};
cls.Cleric.prototype = {
  type : 'leader',
  power : 'divine',
  hp : 5,
  basehp : 12,
  hs : 7,
  skill_slot : 3,
  updateDefenses : function(chr) {
    chr.stats.will.addBonus(2, this, 'class');
  },
  proficiencies : ['simple melee','simple ranged'],
  armour        : ['Cloth','Leather','Hide','Chain'],
  implements    : ['holysymbol'],
  auto_skills   : ['religion'],
  class_skills  : ['arcana','diplomacy','heal','history','insight','religion'],
  features      : ['Heroic.ChannelDivinity'],
  auto_feats    : ['Heroic.RitualCaster']
}



cls.Fighter = function() {};
cls.Fighter.prototype = {
  hp : 6,
  basehp : 15,
  type : 'defender',
  power : 'martial',
  hs : 9,
  skill_slot : 3,
  updateDefenses : function(chr) {
    chr.stats.fort.addBonus(2, this, 'class');
  },
  proficiencies : ['simple melee','military melee','simple ranged','military ranged'],
  armour        : ['Cloth','Leather','Hide','Chain','Scale','LightShield','HeavyShield'],
  class_skills  : ['athletics','endurance','heal','intimidate','streetwise'],
  features      : ['Fighter.CombatChallenge','Fighter.CombatSuperiority']
}



cls.Paladin = function() {};
cls.Paladin.prototype = {
  hp : 6,
  basehp : 15,
  type : 'defender',
  power : 'divine',
  hs : 10,
  skill_slot : 3,
  updateDefenses : function(chr) {
    chr.stats.fort.addBonus(1, this, 'class');
    chr.stats.ref .addBonus(1, this, 'class');
    chr.stats.will.addBonus(1, this, 'class');
  },
  proficiencies : ['simple melee','military melee','simple ranged'],
  armour        : ['Cloth','Leather','Hide','Chain','Scale','Plate','LightShield','HeavyShield'],
  implements    : ['holysymbol'],
  auto_skills   : ['religion'],
  class_skills  : ['diplomacy','endurance','heal','history','insight','intimidate','religion'],
  features      : ['Heroic.ChannelDivinity']
}



cls.Ranger = function() {};
cls.Ranger.prototype = {
  hp : 5,
  basehp : 12,
  type : 'striker',
  power : 'martial',
  hs : 6,
  skill_slot : 4,
  updateDefenses : function(chr) {
    chr.stats.fort.addBonus(1, this, 'class');
    chr.stats.ref.addBonus(1, this, 'class');
  },
  proficiencies : ['simple melee','military melee','simple ranged','military ranged'],
  armour        : ['Cloth','Leather','Hide'],
  class_skills  : ['acrobatics','athletics','dungeoneering','endurance','heal','nature','perception','stealth'],
  features      : ['Heroic.PrimeShot', 'Ranger.HuntersQuarry'],
  dynamic_features  : ['Ranger.ArcherFightingStyle', 'Ranger.TwoBladeFightingStyle']
}



cls.Rogue = function() {};
cls.Rogue.prototype = {
  hp : 5,
  basehp : 12,
  type : 'striker',
  power : 'martial',
  hs : 6,
  skill_slot : 4,
  updateDefenses : function(chr) {
    chr.stats.ref.addBonus(2, this, 'class');
  },
  proficiencies : ['Dagger','HandCrossbow','Shuriken','Sling','ShortSword'],
  armour        : ['Cloth','Leather'],
  auto_skills   : ['stealth','thievery'],
  class_skills  : ['acrobatics','athletics','bluff','dungeoneering','insight','intimidate','perception','stealth','streetwise','thievery'],
  features      : ['Rogue.FirstStrike','Rogue.SneakAttack'],
  dynamic_features	: ['Rogue.ArtfulDodger', 'Rogue.BrutalScoundrel']
}



cls.Warlock = function() {};
cls.Warlock.prototype = {
  hp : 5,
  basehp : 12,
  type : 'striker',
  power : 'arcane',
  hs : 6,
  skill_slot : 4,
  updateDefenses : function(chr) {
    chr.stats.ref.addBonus(1, this, 'class');
    chr.stats.will.addBonus(1, this, 'class');
  },
  proficiencies : ['simple melee','simple ranged'],
  armour        : ['Cloth','Leather'],
  implements    : ['rod','wand','pactblade'],
  class_skills  : ['arcana','bluff','history','insight','intimidate','religion','streetwise','thievery'],
  features		: ['Heroic.PrimeShot', 'Warlock.WarlockPact', 'Warlock.ShadowWalk'],
  dynamic_features	: ['Warlock.FeyPact', 'Warlock.InfernalPact', 'Warlock.StarPact',
          'Warlock.MistyStep', 'Warlock.DarkOnesBlessing', 'Warlock.FateOfTheVoid']
}



cls.Warlord = function() {};
cls.Warlord.prototype = {
  hp : 5,
  basehp : 12,
  type : 'leader',
  power : 'martial',
  hs : 7,
  skill_slot : 4,
  updateDefenses : function(chr) {
    chr.stats.fort.addBonus(1, this, 'class');
    chr.stats.will.addBonus(1, this, 'class');
  },
  proficiencies : ['simple melee','military melee','simple ranged'],
  armour        : ['Cloth','Leather','Hide','Chain','LightShield'],
  class_skills  : ['athletics','diplomacy','endurance','heal','history','intimidate'],
  features      : ['Warlord.CombatLeader'],
  dynamic_features	: ['Warlord.InspiringPresence', 'Warlord.TacticalPresence'],
  feats	: ['Warlord.InspiredRecovery']
}



cls.Wizard = function() {};
cls.Wizard.prototype = {
  hp : 4,
  basehp : 10,
  type : 'controller',
  power : 'arcane',
  hs : 6,
  skill_slot : 3,
  updateDefenses : function(chr) {
    chr.stats.will.addBonus(2, this, 'class');
  },
  proficiencies : ['Dagger','Quarterstaff'],
  armour        : ['Cloth'],
  implements    : ['orb', 'staff', 'wand'],
  auto_skills   : ['arcana'],
  class_skills  : ['arcana','diplomacy','dungeoneering','history','insight','nature','religion'],
  features      : ['Wizard.Cantrips','Wizard.Spellbook'],
  dynamic_features	: ['Wizard.OrbOfImposition', 'Wizard.StaffOfDefense', 'Wizard.WandOfAccuracy'],
  auto_feats    : ['Heroic.RitualCaster'],
  get powers()	{ return []; }
}



cls.Swordmage = function() {};
cls.Swordmage.prototype = {
  book : 'frpg',
  hp : 6,
  basehp : 15,
  type : 'defender',
  power : 'arcane',
  hs : 8,
  skill_slot : 3,
  updateDefenses : function(chr) {
    chr.stats.will.addBonus(2, this, 'class');
  },
  proficiencies : ['simple melee', 'military lightblade', 'military heavyblade', 'simple ranged'],
  armour        : ['Cloth','Leather'],
  implements    : ['lightblade', 'heavyblade'],
  auto_skills   : ['arcana'],
  class_skills  : ['arcana','athletics','diplomacy','endurance','history','insight','intimidate'],
  features      : ['Swordmage.Swordbond'],
  get powers()	{ return []; }
}



cls.Artificer = function() {};
cls.Artificer.prototype = {
  book : 'ebpg',
  type : 'leader',
  power : 'arcane',
  hp : 5,
  basehp : 12,
  hs : 7,
  skill_slot : 4,
  updateDefenses : function(chr) {
    chr.stats.fort.addBonus(1, this, 'class');
    chr.stats.will.addBonus(1, this, 'class');
  },
  proficiencies : ['simple melee','simple ranged'],
  armour        : ['Cloth','Leather'],
  implements    : ['orb', 'rod', 'staff', 'wand'],
  auto_skills   : ['arcana'],
  class_skills  : ['arcana','diplomacy','dungeoneering','heal','history','perception','thievery'],
  features		: ['Artificer.ArcaneReplenishment', 'Artificer.HealingInfusion'],
  auto_feats    : ['Heroic.RitualCaster'],
}

}