// Parse power sumary
chargen.System.Power = {
  regx_TransAbility : /\b(str|con|dex|int|wis|cha)\b/g,
  regx_TransWeapon : /\b(\d\d?)W\b/,
  regx_Line1 : /(attack|utility)?\s*(\d*|feat|feature)\s*(atwill|encounter|daily)\s*([123456]+)?/,
  regx_Line2 : /\s+/,
  regx_Line3 : /(no|interrupt|reaction|free|minor|move|standard|short)?\s*(meleeranged|melee|ranged|blast|burst|wall)?\s*(\d*)\s*(?:in\s*)?(touch|weapon|personal|sight|\d+)?\s*(\/\S*)?/,
  regx_Line4 : /(.*?)([+-]\d+\*?)?\s+vs\.?\s+(.*)/,
//  regx_Line5 : /\s*/,

  // Standard slots comming from level progression
  atwillClassPowerSlot: function(){},
  encounterClassPowerSlot: function(){},
  dailyClassPowerSlot: function(){},
  utilityClassPowerSlot: function(){},
  // A slot that turns its selection into given frequency. Type is optional, may be 'utility'.
  FrequencyPowerSlot : function(frequency, power) {
    this.frequency = frequency;
    if (power && typeof(power) == 'object') {
      this.noOptions = true;
      this.selection = power;
      this.type = power.type == 'utility' ? 'utility' : frequency;
    } else {
      this.type = power || frequency;
    }
  },

  // Attack bonus that increase with tier, like many racial attack powers
  powerAtkTierBonus : function(param) {
    if (this == param.power) {
      for each (let part in chargen.MULTI_ATTACKS) {
        let bonus = this['attack_bonus'+part];
        bonus = bonus + this.char.counts.tier * bonus;
        let f = 'attack'+part;
        if (bonus && this.rules[f] && this.rules[f].addBonus) this.rules[f].addBonus(bonus, this, 'system_power');
      }
    }
  },
  // Plain attack bonus, more commonly seen in class powers
  powerAtkPlainBonus : function(param) {
    if (this == param.power) {
      for each (let part in chargen.MULTI_ATTACKS) {
        let bonus = this['attack_bonus'+part];
        let f = 'attack'+part;
        if (bonus && this.rules[f] && this.rules[f].addBonus) this.rules[f].addBonus(bonus, this, 'system_power');
      }
    }
  },

  initPower : function(pgroup, pname, p) {
    let base = p;
    if (!p || typeof(p)=='string') {
      let summary = p;
      p = function(){};
      chargen.Powers[pgroup][pname] = base = p;
      p = p.prototype;
      if (summary) p.summary = summary;
    } else {
      if (!p.prototype) {
        chargen.Powers[pgroup][pname] = base = function() {};
        base.prototype = p;
      } else {
        p = p.prototype;
      }
      if (p._initialised) return;
    }
    p.text = text.Powers[pgroup][pname];
    p.id = pname;
    p._type = 'power';
    p._Types = 'Powers';
    if (p.summary) this.parseSummary(p, p.summary);
    if (!p.book)  p.book   = 'phb';
    if (!p.group) p.group = pgroup;
    if (!p.type) p.type = 'attack';
    if (!p.action) p.action = 'standard';
    if (!p.attack_type)
      switch (p.area) {
        case 'melee' : p.attack_type = 'melee'; break;
        case 'ranged': p.attack_type = 'ranged'; break;
        case 'meleeranged'   : p.attack_type = 'meleeranged'; break;
        case 'blast' : p.attack_type = 'close'; break;
        case 'wall'  : p.attack_type = 'area'; break;
        case 'burst' : p.attack_type = p.range ? 'area' : 'close'; break;
      }
    if (!p.target) {
      p.target = 1;
      if (p.area && p.area != 'wall')
        if (p.area == 'burst' || p.area=='blast')
          p.target = 'all';
    }
    if (p.accessory && !p.tools) {
      if (p.accessory.indexOf('implement') >= 0)
        p.tools = chargen.Classes[pgroup].prototype.implements.concat();
      else if (p.accessory.indexOf('weapon') >= 0) {
        p.tools = (p.attack_type == 'melee' || p.area == 'burst') ? ['melee'] : (p.attack_type == 'ranged' || p.area == 'blast') ? ['ranged'] : (p.attack_type == 'meleeranged') ? ['melee', 'ranged'] : [];
      }
    }
//    if (!p.critical) p.critical = undefined;
    if (!p.owner) {
      if (chargen.Classes[pgroup]) {
        p.owner = 'class_'+pgroup;
        let fullname = pgroup+'.'+pname;
        if (typeof(p.level) == 'number') {
          if (p.type == 'attack')
            chargen.Classes[pgroup].prototype[p.frequency].push(base);
          else
            chargen.Classes[pgroup].prototype[p.type].push(base);
        } else if (p.level == 'feature')
            chargen.Classes[pgroup].prototype.powers.push(base);
      } else if (chargen.Races[pgroup]) {
        p.owner = 'race_'+pgroup;
        if (p.level == 'feature')
          chargen.Races[pgroup].prototype.powers.push(base);
      } else {
	p.owner = pgroup.toLowerCase();
      }
    }
    if (!p.reset) p.reset = this.reset;
    try { p.rules = chargen.Rule.parseAll(p.text, p); } catch(err) { cerror(["Error parsing "+pname, err]); }
    if (!p.getUsable) p.getUsable = this.getUsable;
    if (!p.setEq) p.setEq = this.setEq;
    if (!p.tar) p.tar = this.shortcut_target;
    if (!p.are) p.are = this.shortcut_area;
    if (!p.atk) p.atk = this.shortcut_attack;
    if (!p.dmg) p.dmg = this.shortcut_damage;
    if (!p.hit) p.hit = this.shortcut_hit;
    if (p.init) { p.init(); delete p.init; }
    p.reset(); // Get all those rule parts in prototype.  I know it is a mess...
  },

  /** Expand one-line power summary into various fields */
  parseSummary : function(p, summary) {
    let attacks = summary.split('!!');
    let [line, line5, line_tool] = attacks[0].split('!', 3);
    let [line1, line2, line3, line4] = (line+'|||').split('|', 4);
  //    clog([p.summary, line1, line2, line3, line4, line5]);
    try {
      if (line1) { // (type) (level) frequency (recharge)
        let [, type, level, frequency, recharge] = this.regx_Line1.exec(trim(line1));
        if (type) p.type = type;
        if (level) p.level = +level || level;
         //(level == 'feature' || level == 'feat') ? text['power_'+level] : +level;
        if (frequency) p.frequency = frequency;
        if (recharge) p.recharge = recharge;
      }

      if (line2) { // power, accessory, energy, effect
        let power = [], accessory = [], energy = [], effect = [];
        for each (let keyword in line2.split(this.regx_Line2)) {
          if (['martial','divine','arcane'].indexOf(keyword) >= 0)
            power.push(keyword);
          else if (['weapon','implement'].indexOf(keyword) >= 0) {
            accessory.push(keyword);
          } else if (['acid','cold','fire','force','lightning','necrotic','poison','psychic','radiant','thunder'].indexOf(keyword) >= 0)
            energy.push(keyword);
          else if (['artifice','charm','conjuration','fear','healing','illusion','poison','polymorph','reliable','sleep','stance','teleportation','zone'].indexOf(keyword) >= 0)
            effect.push(keyword);
        }
        if (power.length > 0) p.power = power;
        if (accessory.length > 0) p.accessory = accessory;
        if (energy.length > 0) p.energy = energy;
        if (effect.length > 0) p.effect = effect;
      }

      if (trim(line_tool) && !p.tools) { // lightblade, crossbow, sling, Dagger
        let tools = trim(line_tool).split(/\s*,\s*/);
        let requirements = [];
        p.tools = [];
        for each (let t in tools) {
          p.tools.push(t);
          requirements.push(text.Equipment.BaseWeapon[t] ? text.Equipment.BaseWeapon[t].title : (text['weapon_'+t] || text['implement_'+t]) );
        }
        p.text.requirements = requirements.join(', ');
      }

      attacks[0] = (line3 || '') + '!' + (line4 || '') + '!' + (line5 || '');

      let parts = chargen.MULTI_ATTACKS.concat();
      for each (let line in attacks) {
        let part = parts.shift();
        [line3, line4, line5] = (line+'!!').split('!', 3);
        this.parseAttack(p, part, line3, line4, line5);
      }
    } catch (err) {
      cerror('Cannot parse "'+p.summary+'"');
      throw err;
    }

    delete p.summary;
  },

  /** Parse attack / attack2 / attack3 */
  parseAttack : function(p, part, line3, line4, line5) {
      // meleerange weapon, melee touch, ranged sight, personal
      // ranged 20, blast 3, burst 2 /allvise
      // burst 1 in 3, wall 8 in 10
      if (trim(line3)) { // (action) (area) (area_size) (range) (target)
        let [, action, area, area_size, range, target] = this.regx_Line3.exec(trim(line3))
        if (action) p.action = action;
        if (area) p.area = area;
        if (area_size)
          if (!range || area != 'ranged') p.area_size = area_size;
          else p.range = area_size;
        if (range)
          p.range = range;
        if (target) p['target'+part] = target.slice(1);
      }

      if (trim(line4)) { // (attack+bonus vs defense)
        let [, attack, atkbonus, defense] = this.regx_Line4.exec(trim(line4));
        if (attack) p['attack'+part] = attack; // + 'Atk'; //.replace(this.regx_TransAbility, '$1Atk');
        if (defense) p['defense'+part] = defense;
        if (atkbonus && part == '') {
          //atkbonus = atkbonus.slice(1);
          if (endsWith(atkbonus, '*')) {
            p.attack_bonus = +atkbonus.slice(0, -1);
            p.onSetPower = this.powerAtkTierBonus;
          } else {
            p['attack_bonus'+part] = +atkbonus;
            p.onSetPower = this.powerAtkPlainBonus;
          }
        }
      }
      if (trim(line5)) { // (hit damage)
        let hit = trim(line5);
        p['hit_damage'+part] = hit.replace(this.regx_TransAbility, '$1M');;
      }
  },

  /* Target & Area combined line builder */
  shortcut_target: function(part, type) {
    var result = this.are(part, type);
    if (!part) part = '';
    if (!type) type = 'getDesc'; else type = 'get'+type;
    var temp = '';
    if (this['target'+part]) {
      if (this.range != 'personal' && this['target'+part] != 1)
        temp = trim( text['target_'+this['target'+part]] || '' );
    } else
      return '';
    if (temp) {
      if (temp.indexOf('{{') >= 0) temp = chargen.Rule.parse(temp)[type](this);
      if (result)
        result = temp + text.hint_part_target_connector + result;
      else
        result = temp;
    }
    return result;
  },

  /* Area combined line builder */
  shortcut_area: function(part, type) {
    if (!part) part = '';
    if (!type) type = 'getDesc'; else type = 'get'+type;
    var result = '';
    if (this['area'+part])      result += text['area_'+this['area'+part]];
    if (this['area_size'+part]) result += ' ' + this['area_size'+part];
    if (this['range'+part])     result += ( this['area_size'+part] ? text.hint_part_range_connector : ' ' )
                               +  ( text['range_'+this['range'+part]] || this['range'+part] ) ;
    result = trim(result);
    if (result && result.indexOf('{{') >= 0) result = chargen.Rule.parse(result)[type](this);
    return result;
  },

  /* Attack vs Defense line builder */
  shortcut_attack: function(part, type) {
    if (!this.rules) return '';
    if (!part) part = '';
    if (!type) type = 'getDesc'; else type = 'get'+type;
    /*
    let temp = {};
    if (this['defense'+part]) temp['defense'+part] = this['defense'+part];
    if (this['attack' +part]) rule['attack' +part] = this['attack'+part];
    */
    var rules = this.rules; //chargen.Rule.parseAll(temp);
//    clog(rules);
    var result = rules['attack'+part] ? rules['attack'+part][type](this) : '';
    if (rules['attack'+part] && rules['defense'+part]) result += window.text.hint_part_attack_connector;
    result += rules['defense'+part] ? rules['defense'+part][type](this) : '';
    return result;
  },

  /* Attack & hit damage line builder */
  shortcut_damage: function(part, type, connector) {
    if (!this.rules) return '';
    let atk = this.atk ? this.atk(part, type) : '';
    if (!part) part = '';
    if (!type) type = 'getDesc'; else type = 'get'+type;
    if (!connector) connector = ', ';
    let dmg = this.rules['hit_damage'+part] ? this.rules['hit_damage'+part][type](this) : '';
    if (atk && dmg) return atk + connector + dmg;
    else if (dmg) return dmg;
    else return atk
  },

  /* Hit damage && effect line builder */
  shortcut_hit: function(part, type) {
    if (!this.rules) return '';
    if (!part) part = '';
    if (!type) type = 'getDesc'; else type = 'get'+type;
    var rules = this.rules;
    var result = rules['hit_damage'+part] ? this.rules['hit_damage'+part][type](this) : '';
    if (rules['hit_damage'+part] && rules['hit'+part]) result += window.text.hint_part_hit_connector;
    if (rules['hit'+part]) {
      let temp = this.rules['hit'+part][type](this);
      if (temp) {
        if (result) temp = temp[0].toLowerCase() + temp.slice(1);
        result += temp;
      }
    }
    return result;
  },

  /* Given an associated list of eq, returns a list of what can be used to make this attack. */
  getUsable: function(eqList) {
    var result = [], result2 = [];
    if (this.accessory) {
      for each (let [slot, eq] in Iterator(eqList)) {
        if (eq.selection) eq = eq.selection;
        if (eq.is) for each (let i in this.tools)
          if (eq.is(i)) { // Match tools.  Now check type.  Wasted on melee and ranged
//            if (this.range != 'weapon' || (this.area != 'melee' && this.area != 'ranged') || eq.is(this.area)) {
            result.push(slot);
            result2.push(slot);
            break;
          }
        else if (eq.cauUseWith && eq.cauUseWith(this))
          result.push(slot);
      }
    } else {
      // No accessory?  No eq then.
    }
    return [result, result2];
  },

  /* Reset power stat to initial, unadjusted state */
  reset: function(oldPower) {
    // Reset basic things
    this.text = cloneObject(text.Powers[this.group][this.id]);
    this.rules = chargen.Rule.parseAll(this.text, this);

    // Reset attack & defense
    for each (let part in chargen.MULTI_ATTACKS) {
      let field = 'attack'+part;
      if (this[field]) {
        let atk = this[field];
        let atkBonus = this.text[field] || '';
        if (this.char && this.char.abilities[atk+'Atk']) {
          this.rules[field] = cloneObject(this.char.abilities[atk+'Atk']);
          if (atkBonus) this.rules[field] = new chargen.Rule.Composite(this.rules[field], chargen.Rule.parse(atkBonus, this));
        } else {
          if (inArray(atk, chargen.STATS))
            this.rules[field] = new chargen.Rule.parse('{{'+atk+'M}}' + atkBonus, this);
          else
            this.rules[field] = new chargen.Rule.parse(atk + atkBonus, this);
        }
      }
      field = 'defense'+part;
      if (this[field]) this.rules[field] = chargen.Rule.parse(text[this[field]] || this[field], this);
      field = 'hit_damage'+part;
      if (this[field]) this.rules[field] = chargen.Rule.parseDamage(this[field], this);
    }
    if (this.char) this.char._updates('resetPower', this );

    this.critical = this.text.critical || '';
    if (this.critical) this.rules.critical = chargen.Rule.parse(this.critical);
  },

  /**
   * Given a piece of eq, set the power to use it and update power rules.
   * Type is as returned by getUsable, ignored for most powers
   */
  setEq: function(eq, type) {
    this.equipment = eq;
    this.equipment_type = type;
    if (this.attack2) this.equipment2 = eq;
    if (this.attack3) this.equipment3 = eq;
    this.reset();
    if (eq && eq.critical) this.critical += eq.critical;
    if (this.critical) this.rules.critical = chargen.Rule.parse(this.critical);
    this.char._updates('onSetPower', {eq: eq, type: type, char: this.char, power: this} );
  }
};
let (power_sys = chargen.System.Power) {
  power_sys.atwillClassPowerSlot.prototype = {
    type: 'atwill',
    bonus_options : [],
    get options() {
      return this.char.classes.heroic.atwill.concat(this.bonus_options);
    }
  };
  power_sys.encounterClassPowerSlot.prototype = {
    type : 'encounter',
    bonus_options : [],
    get options() {
      let target_level = this.level || this.char.lv;
      return [p for each (p in this.char.classes.heroic.encounter.concat(this.bonus_options)) if (p.prototype.level <= target_level)];
    }
  };
  power_sys.dailyClassPowerSlot.prototype = {
    type: 'daily',
    bonus_options : [],
    get options() {
      let target_level = this.level || this.char.lv;
      return [p for each (p in this.char.classes.heroic.daily.concat(this.bonus_options)) if (p.prototype.level <= target_level)];
    }
  };
  power_sys.utilityClassPowerSlot.prototype = {
    type: 'utility',
    bonus_options : [],
    get options() {
      let target_level = this.level || this.char.lv;
      return [p for each (p in this.char.classes.heroic.utility.concat(this.bonus_options)) if (p.prototype.level <= target_level)];
    }
  };
  // FrequencyPowerSlot provides no options; selection must be set by creator.
  power_sys.FrequencyPowerSlot.prototype = {
    get level() { return this.selection ? this.selection.level : 1 },
    resetPower : function(power) { if (power == this.selection) power.frequency = this.frequency; }
  };
}

let (power = chargen.Powers) {
  let strcondex = text.strM + '/' + text.conM + '/' + text.dexM;
  let strdex = text.strM + '/' + text.dexM;

  power.Dragonborn = {};
  power.Dragonborn.DragonbornBreath = {
    summary: 'feature encounter | | minor blast 3 | str+2* vs ref ! {{chr.counts.tier+1+"d6";||conM||damage,roll}}',
    options: { acid:'acid', cold:'cold', fire:'fire', lightning:'lightning', poison:'poison' },
    options2: [ 'str', 'dex', 'con' ],
    get energy() { return (this.choice) ? [this.choice] : []; },
    get attack() { return this.choice2 || strcondex; },
    resetPower: function(power) {
      if (power == this && this.choice) this.rules.hit_damage.properties.push(this.choice);
    }
  };

  power.Eladrin = {};
  power.Eladrin.FeyStep = 'utility feature encounter | teleportation | move personal';

  power.Elf = {};
  power.Elf.ElvenAccuracy = 'utility feature encounter | | free personal';

  power.Halfling = {};
  power.Halfling.SecondChance = 'utility feature encounter | | interrupt personal';

  power.Tiefling = {};
  power.Tiefling.InfernalWrath = 'utility feature encounter | | minor personal';


  power.Bugbear = {
    PredatoryEye : 'feature encounter | | minor personal'
  };

  power.Doppelganger = {
    ChangeShape : 'utility feature atwill | polymorph | minor personal'
  };

  power.Drow = {
    CloudOfDarkness	: 'utility feature encounter | | minor burst 1',
    Darkfire		: {
      summary : 'feature encounter | | minor ranged 10 | str+2* vs ref',
      options : [ 'int', 'wis', 'cha' ],
      get attack() { return this.choice || strcondex }
    }
  };

  power.Githyanki = {
    TelekineticLeap : 'utility feature encounter | | move ranged 10 /u1a'
  };

  power.Githzerai = {
    IronMind : 'utility feature encounter | | interrupt personal'
  };

  power.Gnoll = {
    FerociousCharge : 'feature encounter | | personal'
  };

  power.Gnome = {
    FadeAway : 'utility feature encounter | illusion | reaction personal'
  };

  power.Goblin = {
    GoblinTactics : 'utility feature atwill | | reaction personal'
  };

  power.Hobgoblin = {
    HobgoblinResilience : 'utility feature encounter | | reaction personal'
  };

  power.Kobold = {
    Shifty : 'utility feature atwill | | minor personal'
  };

  power.Minotaur = {
    GoringCharge : 'feature encounter | | melee 1 | str+2* vs ac ! {{(1+chr.counts.tier)+"d6";||strM||dr}}'
  };

  power.Orc = {
    WarriorsSurge : 'feature encounter | healing weapon | melee weapon | str vs ac ! {{(1+chr.counts.epic)+"W";||strM||wdr}}'
  };

  power.Shadarkai = {
    ShadowJaunt : 'utility feature encounter | teleportation | move personal'
  };

  power.LongtoothShifter = {
    LongtoothShifting : 'utility feature encounter | healing | minor personal'
  };

  power.RazorclawShifter = {
    RazorclawShifting : 'utility feature encounter | | minor personal'
  };

  power.Warforged = {
    WarforgedResolve : 'utility feature encounter | | minor personal'
  };

  power.Genasi = {
    Earthshock	: {
      summary	: 'feature encounter | | minor burst 1 | str+2* vs fort',
      options2 : [ 'str', 'con', 'dex' ],
      get attack() { return this.choice2 || strcondex }
    },
    Firepulse	: {
      summary	: 'feature encounter | fire | reaction melee 1 /trige | str+2* vs ref',
      options2 : [ 'str', 'con', 'dex' ],
      get attack() { return this.choice2 || strcondex },
      get hit_damage() { return this.choice2
        ? '{{chr.counts.tier+1+"d6";||'+this.choice2+'M||fire,damage,roll}}'
        : '{{chr.counts.tier+1+"d6";||strM/dexM/conM||fire,damage,roll}}' }
    },
    PromiseOfStorm : 'utility feature encounter | lightning, thunder | minor personal',
    Swiftcurrent : 'utility feature encounter | | move personal',
    Windwalker : 'utility feature encounter | | move personal'
  };

  power.Cleric = {};
  // Cleric Features
  power.Cleric.DivineFortune	= 'utility feature encounter | divine | free personal';
  power.Cleric.TurnUndead		= {
    summary : 'feature encounter | divine implement radiant | burst /allundead | wis vs will ! {{chr.counts.halfTier5+1+"d10";||wisM||idr,radiant}}',
    range : '{{2+chr.counts.tier*3;}}'
  }
  power.Cleric.HealingWord		= {
    summary : 'utility feature encounter | divine healing | minor burst /u1a',
    range : '{{5+chr.counts.tier*5;}}'
  }
  // Feats
  power.Feat = {};
  power.Feat.ArmorOfBahamut = 'utility feat encounter | divine | interrupt ranged 5';
  power.Feat.AvandrasRescue = 'utility feat encounter | divine | move melee 1 /1a';
  power.Feat.CorellonsGrace  = 'utility feat encounter | divine | interrupt ranged 10';
  power.Feat.HarmonyOfErathis  = 'utility feat encounter | divine | minor ranged 10 /1a';
  power.Feat.IounsPoise = 'utility feat encounter | divine | minor ranged 5 /u1a';
  power.Feat.KordsFavor = 'utility feat encounter | divine healing | free';
  power.Feat.MelorasTide = 'utility feat encounter | divine healing | minor ranged 5 /u1a_b';
  power.Feat.MoradinsResolve = 'utility feat encounter | divine | minor personal';
  power.Feat.PelorsRadiance = {
    summary : 'feat encounter | divine | burst | wis vs will ! {{1+chr.counts.halfTier5+"d12";||wisM||idr,radiance}}',
    get area_size() { return 1+chr.counts.tier*2; }
  };
  power.Feat.RavenQueensBlessing = 'utility feat encounter | divine healing | free ranged 10';
  power.Feat.SehaninesReversal = 'feat encounter | divine | no ranged 5';
  power.Feat.PowerOfAmaunator = 'feat encounter | divine radiant | free personal';

  // At Will
  power.Cleric.LanceOfFaith		= '1 atwill | divine implement radiant | ranged 5 | wis vs ref ! {{1+chr.counts.epic+"d8";||wisM||idr,radiant}}';
  power.Cleric.PriestsShield	= '1 atwill | divine weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  power.Cleric.RighteousBrand 	= '1 atwill | divine weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  power.Cleric.SacredFlame		= '1 atwill | divine implement radiant | ranged 5 | wis vs ref ! {{1+chr.counts.epic+"d6";||wisM||radiant,damage,roll,implement}}';
  // Encounter 1
  power.Cleric.CauseFear		= '1 encounter | divine fear implement | ranged 10 | wis vs will';
  power.Cleric.DivineGlow		= '1 encounter | divine implement radiant | blast 3 /alle | wis vs ref ! d8+wis';
  power.Cleric.HealingStrike	= '1 encounter | divine healing weapon radiant | melee weapon | str vs ac ! 2W+str';
  power.Cleric.WrathfulThunder	= '1 encounter | divine thunder weapon | melee weapon | str vs ac ! 1W+str';
  // Daily 1
  power.Cleric.AvengingFlame	= '1 daily | divine fire weapon | melee weapon | str vs ac ! 2W+str';
  power.Cleric.BeaconOfHope		= '1 daily | divine healing implement | burst 3 /alle | wis vs will';
  power.Cleric.CascadeOfLight	= '1 daily | divine implement radiant | ranged 10 | wis vs will ! 3d8+wis';
  power.Cleric.GuardianOfFaith	= '1 daily | divine conjuration radiant implement | ranged 5 | wis vs fort ! d8+wis';
  // Utility 2
  power.Cleric.Bless			= 'utility 2 daily | divine | burst 20 /ualla';
  power.Cleric.CureLightWounds	= 'utility 2 daily | divine healing | touch /u1c';
  power.Cleric.DivineAid		= 'utility 2 encounter | divine | ranged 5 /u1a';
  power.Cleric.Sanctuary		= 'utility 2 encounter | divine | ranged 10 /u1c';
  power.Cleric.ShieldOfFaith	= 'utility 2 daily | divine | burst 5 /ualla';
  // Encounter 3
  power.Cleric.BlazingBeacon	= '3 encounter | divine radiant weapon | melee weapon | str vs ac ! 1W+str';
  power.Cleric.Command			= '3 encounter | divine charm implement | ranged 10 | wis vs will';
  power.Cleric.DauntingLight	= '3 encounter | divine implement radiant | ranged 10 | wis vs ref ! 2d10+wis';
  power.Cleric.SplittheSky		= '3 encounter | divine thunder weapon | melee weapon | str vs fort ! 1W+str';
  // Daily 5
  power.Cleric.ConsecratedGround	= '5 daily | divine healing radiant zone | burst 1 | ! 1d6+cha';
  power.Cleric.RuneOfPeace		= '5 daily | charm divine weapon | melee weapon | str vs will ! 1W+str';
  power.Cleric.SpiritualWeapon	= '5 daily | conjuration divine implement | ranged 10 | wis vs ac ! 1d10+wis';
  power.Cleric.WeaponOfTheGods	= '5 daily | divine radiant weapon | melee touch /1heldweapon';
  // Utility 6
  power.Cleric.BastionOfHealth	= 'utility 6 encounter | divine healing | minor ranged 10 /u1a';
  power.Cleric.CureSeriousWounds		= 'utility 6 daily | divine healing | melee touch /u1c';
  power.Cleric.DivineVigor	= 'utility 6 daily | divine healing | minor burst 5 /ualla';
  power.Cleric.HolyLantern	= 'utility 6 atwill | divine conjuration | ranged 3';
  // Encounter 7
  power.Cleric.AweStrike = '7 encounter | divine fear weapon | melee weapon | str vs will ! 1W+str';
  power.Cleric.BreakTheSpirit = '7 encounter | charm divine implement radiant | ranged 10 | wis vs will ! 2d8+wis';
  power.Cleric.SearingLight = '7 encounter | divne implement radiant | ranged 10 | wis vs ref ! 2d6+wis';
  power.Cleric.StrengthenTheFaithful = '7 encounter | divine healing weapon | melee weapon | str vs ac ! 2W+str';
  // Daily 9
  power.Cleric.AstralDefenders = '9 daily | conjuration divine implement radiant | ranged 10 | wis vs ref ! 1d10+wis';
  power.Cleric.BladeBarrier = '9 daily | conjuration divine implement | wall 5 in 10 | ! 3d6+wis';
  power.Cleric.DivinePower = '9 daily | divine healing radiant weapon | burst 2 | str vs fort ! 2W+str';
  power.Cleric.FlameStrike = '9 daily | divine fire implement | burst 2 in 10 | wis vs ref ! 2d10+wis';
  // Utility 10
  power.Cleric.AstralRefuge = 'utility 10 daily | divine healing teleportation | melee touch /1a';
  power.Cleric.KnightsOfUnyieldingValor = 'utility 10 daily | conjuration divine | ranged 10';
  power.Cleric.MassCureLightWounds = 'utility 10 daily | divine healing | burst 5 /ualla';
  power.Cleric.ShieldingWord = 'utility 10 encounter | divine | interrupt ranged 5';

  power.Fighter = {};
  // At Will
  power.Fighter.Cleave	= '1 atwill | martial weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  power.Fighter.ReapingStrike	= {
    summary : '1 atwill | martial weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}',
    onSetPower: function(param) { if (param.power == this) {
      this.text.miss = '{{' + ((param.eq && param.eq.hand >= 2) ? 'strMod' : 'Math.floor(chr.strMod/2);' )
                     + '| ||wdm}} ' + this.text.miss;
      this.rules.miss = chargen.Rule.parse(this.text.miss);
    } }
  };
  power.Fighter.SureStrike	=  '1 atwill | martial weapon | melee weapon | str+2 vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  power.Fighter.TideofIron	= '1 atwill | martial weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  // Encounter 1
  power.Fighter.CoveringAttack	= '1 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Fighter.PassingAttack	= '1 encounter | martial weapon | melee weapon | str vs ac ! 1W+str !! /1sec ! str+2 vs ac ! 1W+str';
  power.Fighter.SpinningSweep		= '1 encounter | martial weapon | melee weapon | str vs ac ! 1W+str';
  power.Fighter.SteelSerpentStrike	= '1 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  // Daily 1
  power.Fighter.BruteStrike		= '1 daily | martial weapon reliable | melee weapon | str vs ac ! 3W+str';
  power.Fighter.ComebackStrike	= '1 daily | martial weapon reliable healing | melee weapon | str vs ac ! 2W+str';
  power.Fighter.VillainsMenace	= '1 daily | martial weapon | melee weapon | str vs ac ! 2W+str';
  // Utility 2
  power.Fighter.BoundlessEndurance		= 'utility 2 daily | martial healing stance | minor personal';
  power.Fighter.GetOverHere		= 'utility 2 encounter | martial | move melee 1 /1adja';
  power.Fighter.NoOpening		= 'utility 2 encounter | martial | interrupt personal';
  power.Fighter.Unstoppable		= 'utility 2 daily | martial healing | minor personal';
  // Encounter 3
  power.Fighter.ArmorPiercingThrust	= {
    summary	: '3 encounter | martial weapon | melee weapon | str vs ref ! 1W+str',
    onSetPower : function(param) {
      if (param.power == this && param.eq && (param.eq.is('lightblade') || param.eq.is('spear')) ) {
        this.rules.attack.addBonus('dexM', this, 'system_power');
        this.rules.hit_damage.addBonus('dexM', this, 'system_power');
      }
    }
  };
  power.Fighter.CrushingBlow	= {
    summary : '3 encounter | martial weapon | melee weapon | str vs ac ! 2W+str',
    onSetPower : function(param) { if (param.power == this && param.eq && (param.eq.is('axe') || param.eq.is('hammer') || param.eq.is('mace')) )
      param.power.rules.hit_damage.addBonus('conM', this, 'system_power');
    }
  };
  power.Fighter.DanceOfSteel	= '3 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Fighter.PreciseStrike	= '3 encounter | martial weapon | melee weapon | str+4 vs ac ! 1W+str';
  power.Fighter.RainOfBlows		= {
    summary : '3 encounter | martial weapon | melee weapon | str vs ac ! 1W+str !! /same1c ! str vs ac ! 1W+str',
    onSetPower : function(param) {
      if (param.power == this && param.char.abilities.dex >= 15 && param.eq && (param.eq.is('lightblade') || param.eq.is('spear') || param.eq.is('flail') ) )
      ; else for each (let field in ['hit', 'target2', 'attack2', 'defense2', 'hit_damage2']) delete this.rules[field];
    }
  }
  power.Fighter.SweepingBlow	= {
    summary : '3 encounter | martial weapon | burst 1 /allvise | str vs ac ! 1W+str',
    tools	: ['melee'],
    onSetPower : function(param) {
      if (param.power == this && param.eq && (param.eq.is('axe') || param.eq.is('flail') || param.eq.is('heavyblade') || param.eq.is('pick')) )
      param.power.rules.attack.addBonus(Math.floor(param.char.strM/2), this, 'system_power');
    }
  }
  //
  power.Fighter.CrackTheShell = '5 daily | martial reliable weapon | melee weapon | str vs ac  ! 2W+str';
  power.Fighter.DizzyingBlow = '5 daily | martial reliable weapon | melee weapon | str vs ac ! 3W+str';
  power.Fighter.RainOfSteel = {
    summary : '5 daily | martial stance weapon | personal | ! 1W',
    tools : ['melee']
  }
  //
  power.Fighter.BattleAwareness = 'utility 6 daily | martial | no personal';
  power.Fighter.DefensiveTraining = 'utility 6 daily | martial stance | minor personal';
  power.Fighter.Unbreakable = 'utility 6 encounter | martial | reaction personal';
  //
  power.Fighter.ComeAndGetIt = '7 encounter | martial weapon | burst 3 /allvise | str vs ac ! 1W+str';
  power.Fighter.GriffonsWrath = '7 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Fighter.IronBulwark = '7 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Fighter.RecklessStrike = '7 encounter | martial weapon | melee weapon | str-2 vs ac ! 3W+str';
  power.Fighter.SuddenSurge = '7 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  //
  power.Fighter.ShiftTheBattlefield = '9 daily | martial weapon | burst 1 /allvise | str vs ac ! 2W+str';
  power.Fighter.ThicketOfBlades = '9 daily | martial reliable weapon | burst 1 /allvise | str vs ac ! 3W+str';
  power.Fighter.VictoriousSurge = '9 daily | healing martial reliable weapon | melee weapon | str vs ac ! 3W+str';
  //
  power.Fighter.IntoTheFray = 'utility 10 encounter | martial | minor personal';
  power.Fighter.LastDitchEvasion = 'utility 10 daily | martial | interrupt personal';
  power.Fighter.StalwartGuard = 'utility 10 daily | martial stance | minor personal';

  power.Paladin = {};
  //
  power.Paladin.DivineMettle	= 'utility feature encounter | divine | minor burst 10/1';
  power.Paladin.DivineStrength	= 'utility feature encounter | divine | minor personal';
  power.Paladin.DivineChallenge	= 'feature atwill | divine radiant | minor burst 5/1';
  power.Paladin.LayOnHands		= 'utility feature atwill | divine healing | minor touch';
  //
  power.Paladin.BolsteringStrike	= '1 atwill | divine weapon | melee weapon | cha vs ac ! {{1+chr.counts.epic+"W";||chaM||wdr}}';
  power.Paladin.EnfeeblingStrike	= '1 atwill | divine weapon | melee weapon | cha vs ac ! {{1+chr.counts.epic+"W";||chaM||wdr}}';
  power.Paladin.HolyStrike			= '1 atwill | divine radiant weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  power.Paladin.ValiantStrike		= '1 atwill | divine weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  //
  power.Paladin.FearsomeSmite		= '1 encounter | divine fear weapon | melee weapon | cha vs ac ! 2W+cha';
  power.Paladin.PiercingSmite		= '1 encounter | divine weapon | melee weapon | str vs ref ! 2W+str';
  power.Paladin.RadiantSmite		= '1 encounter | divine radiant weapon | melee weapon | str vs ac ! 2W+str+wis';
  power.Paladin.ShieldingSmite		= '1 encounter | divine weapon | melee weapon | cha vs ac ! 2W+cha';
  //
  power.Paladin.OnPainOfDeath		= '1 daily | divine implement | ranged 5 | cha vs will ! 3d8+cha';
  power.Paladin.PaladinsJudgment	= '1 daily | divine healing weapon | melee weapon | str vs ac ! 3W+str';
  power.Paladin.RadiantDelirium		= '1 daily | divine implement radiant | ranged 5 | cha vs ref ! 3d8+cha';
  //
  power.Paladin.AstralSpeech		= 'utility 2 daily | divine | minor personal';
  power.Paladin.MartyrsBlessing		= 'utility 2 daily | divine | interrupt burst 1/na';
  power.Paladin.SacredCircle		= 'utility 2 daily | divine implement zone | burst 3/na';
  //
  power.Paladin.ArcingSmite			= '3 encounter | divine weapon | melee weapon /12 | str vs ac ! 1W+str';
  power.Paladin.InvigoratingSmite	= '3 encounter | divine healing weapon | melee weapon | cha vs will ! 2W+cha';
  power.Paladin.RighteousSmite		= '3 encounter | divine healing weapon | melee weapon | cha vs ac ! 2W+cha';
  power.Paladin.StaggeringSmite		= '3 encounter | divine weapon | melee weapon | str vs ac ! 2W+str';
  // paladin attack 5
  power.Paladin.HallowedCircle = '5 daily | divine implement zone | burst 3 /alle | cha vs ref ! 2d6+cha';
  power.Paladin.MartyrsRetribution = '5 daily | divine radiant weapon | melee weapon | str vs ac ! 4W+str';
  power.Paladin.SignOfVulnerability = '5 daily | divine implement radiant | ranged 5 | cha vs fort ! 3d8+cha';
  //
  power.Paladin.DivineBodyguard = 'utility 6 daily | divine | minor ranged 5 /1a';
  power.Paladin.OneHeartOneMind = 'utility 6 daily | divine | minor burst 6 /ualla';
  power.Paladin.WrathOfTheGods = 'utility 6 daily | divine | minor burst 1 /ualla';
  //
  power.Paladin.BeckonFoe = '7 encounter | divine implement | ranged 5 | cha vs will ! 2d10+cha';
  power.Paladin.BenignTransposition = '7 encounter | divine teleportaion weapon | melee weapon /1ainwis !! /1e ! cha vs ac ! 2W+cha';
  power.Paladin.DivineReverence = '7 encounter | divine implement radiant | burst 1 /alle | cha vs will ! 1d8+cha';
  power.Paladin.ThunderSmite = '7 encounter | divine thunder weapon | melee weapon | str vs ac ! 2W+str';
  //
  power.Paladin.CrownOfGlory = '9 daily | divine implement radiant | burst 1 /alle | cha vs will ! 2d8+cha';
  power.Paladin.OneStandsAlone = '9 daily | divine implement radiant | burst 1 /alle | cha vs will ! 2d8+cha';
  power.Paladin.RadiantPulse = '9 daily | divine implement radiant | ranged 10 | cha vs fort ! 1d10+cha !! /allsecadj ! cha vs fort ! d10+cha';
  //
  power.Paladin.CleansingSpirit = 'utility 10 encounter | divine | minor ranged 5 /u1a';
  power.Paladin.NobleShield = 'utility 10 daily | divine | interrupt personal';
  power.Paladin.TurnTheTide = 'utility 10 daily | divine | burst 3 /ualla';
  //
  power.Paladin.RenewingSmite		= '13 encounter | healing weapon | melee weapon | cha vs ac ! 2W+cha';
  power.Paladin.BindingSmite		= '27 encounter | weapon | melee weapon | cha vs will ! 2W+wis';

  // Automatically adds 'str' or 'dex' to attack / damage
  chargen.System.Power.MeleeRangedPower = function(summary) {
    this.summary = summary;
    this.power_data = {};
  };
  chargen.System.Power.MeleeRangedPower.prototype = {
    init: function() {
      for each (let part in chargen.MULTI_ATTACKS) {
        if (this['attack'+part]) {
          let atk = 'attack'+part;
          delete this[atk];
          this.__defineGetter__(atk, function(){ return this.equipment
            ? ( this.equipment_type == 'ranged' ? 'dex' : 'str' )
            : strdex ; } );
        }
        if (this['hit_damage'+part]) {
          let hd = 'hit_damage'+part;
          this.power_data[hd] = chargen.Rule.parseDamage(this[hd], this);
          delete this[hd];
          this.__defineGetter__(hd, function(){ return cloneObject(this.power_data[hd]).addBonus ( this.equipment
            ? ( this.equipment_type == 'ranged' ? 'dexM' : 'strM' )
            : strdex  ) ; } );
        }
      }
    }
  };

  // Powers that requires two weapons (or optional ranged weapon) to use
  chargen.System.Power.DualWeaponPower = function(damage, ranged, summary) {
    this.summary = summary;
    if (damage[0] != '{') damage = '{{' + damage.replace(/ !! /, ' ||wdr}} !! {{') + '||wdr}}';
    let melee = damage.replace(/msrd/g, 'strM').split(/\s*!!\s*/);
    this.dual_data = {
      attack_count : melee.length,
      melee_damage : melee,
      general_damage : melee
    };
    if (ranged) {
      this.dual_data.ranged_damage = damage.replace(/msrd/g, 'dexM').split(/\s*!!\s*/);
      this.dual_data.general_damage = damage.replace(/msrd/g, strdex).split(/\s*!!\s*/);
    }
    for each (let i in chargen.MULTI_ATTACKS.concat().splice(0, melee.length) ) {
      delete this['hit_damage' + i];
      this.__defineGetter__('hit_damage' + i, let (index = i ? i-1 : 0) function() {
        return this.equipment_type
          ? ( this.equipment_type == 'ranged'
                ? this.dual_data.ranged_damage[index]
                : this.dual_data.melee_damage[index] )
          : this.dual_data.general_damage[index]; } );
      if (i) {
        delete this['attack' + i];
        delete this['equipment' + i];
        this.__defineGetter__('attack'+i, function(){ return this.attack; } );
        this.__defineSetter__('attack'+i, function(){ } );
        this.__defineGetter__('equipment'+i, (i % 2 == 0)
          ? function(){ return this.equipment_melee == this.equipment ? this.equipment_offhand : this.equipment; }
          : function(){ return this.equipment; } );
        this.__defineSetter__('equipment'+i, function(){ } ); // Surpress setter warning
      }
    }
  }
  chargen.System.Power.DualWeaponPower.prototype = {
    summary	: '1 atwill | martial weapon | meleeranged weapon | str vs ac ! {{1+chr.counts.epic+"W";||wdr}}',
    get attack() { if (this.equipment) return this.equipment_type == 'ranged' ? 'dex' : 'str'; else return strdex; },
    set attack() {},
    getUsable	: function(eqList) {
      var result1 = [], result2 = [];
      this.equipment_melee = this.equipment_offhand = undefined;
      if (eqList.melee.selection && eqList.offhand.selection) {
        result1.push('melee'); result2.push('melee');
        if (this.dual_data.attack_count == 1) {
          result1.push('offhand'); result2.push('melee'); // Alternative weapon
        }
//        if (this._attack_count > 2) { result1.push('melee'); result2.push('melee'); }
//        if (this._attack_count > 3) { result1.push('offhand'); result2.push('melee'); }
        this.equipment_melee = eqList.melee.selection;
        this.equipment_offhand = eqList.offhand.selection;
      }
      if (this.dual_data.ranged_damage)
        if (eqList.ranged.selection) {
          result1.push('ranged'); result2.push('ranged');
          this.equipment_ranged = eqList.ranged.selection;
        } else {
          this.equipment_ranged = undefined;
        }
      return [result1, result2];
    }
  }

  power.Ranger = {};
//  power.Ranger.HuntersQuarry = 'feature atwill | melee weapon | minor /nearvise';
  //
  power.Ranger.CarefulAttack	= new chargen.System.Power.DualWeaponPower (
    '{{1+chr.counts.epic+"W";||wdr}}', true,
    '1 atwill | martial weapon | meleeranged weapon | str vs ac');
  power.Ranger.CarefulAttack.attack_bonus	= 2;
  power.Ranger.CarefulAttack.onSetPower	= chargen.System.Power.powerAtkPlainBonus;
  power.Ranger.HitAndRun		= '1 atwill | martial weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  power.Ranger.NimbleStrike		= '1 atwill | martial weapon | ranged weapon | dex vs ac ! {{1+chr.counts.epic+"W";||dexM||wdr}}';
  power.Ranger.TwinStrike	= new chargen.System.Power.DualWeaponPower (
    '{{1+chr.counts.epic+"W";||wdr}} !! {{1+chr.counts.epic+"W";||wdr}}', true,
    '1 atwill | martial weapon | meleeranged weapon /12 | str vs ac !! ! str vs ac' );

  // Ranger encounter 1
  power.Ranger.DireWolverineStrike	= new chargen.System.Power.DualWeaponPower (
    '1W+strM', false, '1 encounter | martial weapon | burst 1 /allvise | str vs ac' );
  power.Ranger.EvasiveStrike		= new chargen.System.Power.MeleeRangedPower(
    '1 encounter | martial weapon | meleeranged weapon | str vs ac ! 2W' );
  power.Ranger.FoxsCunning			= '1 encounter | martial weapon | reaction meleeranged weapon';
  power.Ranger.TwoFangedStrike	= new chargen.System.Power.DualWeaponPower (
    '1W+msrd !! 1W+msrd', true, '1 encounter | martial weapon | meleeranged weapon | str vs ac !! ! str vs ac' );
  // Ranger daily 1
  power.Ranger.HuntersBearTrap		= new chargen.System.Power.MeleeRangedPower(
    '1 daily | martial weapon | meleeranged weapon | str vs ac ! 2W' );
  power.Ranger.JawsOfTheWolf		= new chargen.System.Power.DualWeaponPower (
    '2W+strM !! 2W+strM', false, '1 daily | martial weapon | meleeranged weapon | str vs ac !! ! str vs ac' );
  power.Ranger.SplitTheTree		= '1 daily | martial weapon | ranged weapon /2in3 | dex vs ac ! 2W+dex';
  power.Ranger.SuddenStrike		= new chargen.System.Power.DualWeaponPower (
    '1W !! 2W+strM', false, '1 daily | martial weapon | melee weapon | str vs ac !! ! str vs ac' );
  power.Ranger.SuddenStrike.__defineGetter__('equipment', function() { return this.equipment_type == 'ranged' ? this.equipment_ranged : this.equipment_offhand });
  power.Ranger.SuddenStrike.__defineGetter__('equipment2', function() { return this.equipment_type == 'ranged' ? this.equipment_ranged : this.equipment_melee });
  power.Ranger.SuddenStrike.__defineSetter__('equipment', function() {} );
  power.Ranger.SuddenStrike.__defineSetter__('equipment2', function() {} );
  // Ranger utility 2
  power.Ranger.CrucialAdvice		= 'utility 2 encounter | martial | reaction ranged 5';
  power.Ranger.UnbalancingParry		= 'utility 2 encounter | martial | reaction melee 1';
  power.Ranger.YieldGround			= 'utility 2 encounter | martial | reaction personal';
  // Ranger encounter 3
  power.Ranger.CutAndRun			= new chargen.System.Power.DualWeaponPower (
    '1W+msrd !! 1W+msrd', true, '3 encounter | martial weapon | meleeranged weapon | str vs ac !! ! str vs ac' );
  power.Ranger.DisruptiveStrike		= new chargen.System.Power.MeleeRangedPower(
    '3 encounter | martial weapon | interrupt meleeranged weapon | str vs ac ! 1W' );
  power.Ranger.ShadowWaspStrike		= new chargen.System.Power.MeleeRangedPower(
    '3 encounter | martial weapon | meleeranged weapon | str vs ref ! 2W' );
  power.Ranger.ThundertuskBoarStrike	= new chargen.System.Power.DualWeaponPower (
    '1W+msrd !! 1W+msrd', true, '3 encounter | martial weapon | meleeranged weapon | str vs ac !! ! str vs ac' );
  // ranger attack 5
  power.Ranger.ExcruciatingShot = '5 daily | martial weapon | ranged weapon | dex vs ac ! 3W+dex ';
  power.Ranger.FrenziedSkirmish = new chargen.System.Power.DualWeaponPower (
    '1W+str !! 1W+str', false, '5 daily | martial weapon | melee weapon | str vs ac ! !! ! str vs ac ' );
  power.Ranger.SplinteringShot = '5 daily | martial weapon | ranged weapon | dex vs ac ! 3W+dex ';
  power.Ranger.TwoWolfPounce = new chargen.System.Power.DualWeaponPower (
    '2W+str !! 2W+str', false, '5 daily | marital weapon | melee weapon | str vs ac ! !! /1sec ! str vs ac' );
  // utility 6
  power.Ranger.EvadeAmbush = 'utility 6 daily | martial | no ranged sight';
  power.Ranger.SkilledCompanion = 'utility 6 daily | martial | minor ranged 10 /1a';
  power.Ranger.WeaveThroughTheFray = 'utility 6 encounter | martial | interrupt personal';
  // Ranger Attack 7
  power.Ranger.ClawsOfTheGriffon = new chargen.System.Power.DualWeaponPower (
  '2W+str !! 1W+str', false, '7 encounter | martial weapon | melee weapon | str vs ac !! ! str vs ac' );
  power.Ranger.HawksTalon = new chargen.System.Power.MeleeRangedPower(
    '7 encounter | martial weapon | meleeranged weapon | str vs ac ! 2W');
  power.Ranger.HawksTalon.resetPower = function(power){ if (power == this) this.rules.attack.addBonus('wisM'); }
  power.Ranger.SpikesOfTheManticore = '7 encounter | martial weapon | ranged weapon /12 | dex vs ac ! 2W+dex !! ! dex vs ac 1W+dex';
  power.Ranger.SweepingWhirlwind = new chargen.System.Power.DualWeaponPower (
    '1W+str', false, '7 encounter | martial weapon | burst 1 /alle | str vs ac' );
  // Ranger Attack 9
  power.Ranger.AttacksOnTheRun = new chargen.System.Power.MeleeRangedPower(
    '9 daily | martial weapon | meleeranged weapon /12 | str vs ac ! 3W !! ! str vs ac ! 3W' );
  power.Ranger.CloseQuartersShot = '9 daily | martial weapon | ranged 1 /1adje | dex vs ac ! 4W+dex ';
  power.Ranger.SprayOfArrows = '9 daily | martial weapon | blast 3 /alle | dex vs ac ! 2W+dex ';
  power.Ranger.SwirlingLeavesOfSteel = new chargen.System.Power.DualWeaponPower (
    '2W+str', false, '9 daily | martial weapon | burst 1 /allvise | str vs ac ! 2W+str ' );
  //Utility 10
  power.Ranger.ExpeditiousStride = 'utility 10 encounter | martial | minor personal';
  power.Ranger.OpenTheRange = 'utility 10 daily | martial | interrupt personal';
  power.Ranger.UndauntedStride = 'utility 10 daily | martial stance | minor personal';



  power.Rogue = {};
  power.Rogue.DeftStrike		= '1 atwill | martial weapon | meleeranged weapon | dex vs ac ! {{1+chr.counts.epic+"W";||dexM||wdr}} ! crossbow,lightblade,sling';
  power.Rogue.PiercingStrike	= '1 atwill | martial weapon | melee weapon | dex vs ref ! {{1+chr.counts.epic+"W";||dexM||wdr}} ! lightblade';
  power.Rogue.RiposteStrike		= '1 atwill | martial weapon | melee weapon | dex vs ac ! {{1+chr.counts.epic+"W";||dexM||wdr}} ! lightblade';
  power.Rogue.SlyFlourish		= '1 atwill | martial weapon | meleeranged weapon | dex vs ac ! {{1+chr.counts.epic+"W";||dexM||chaM||wdr}} ! crossbow,lightblade,sling';
  //
  power.Rogue.DazingStrike		= '1 encounter | martial weapon | melee weapon | dex vs ac ! 1W+dex ! lightblade';
  power.Rogue.KingsCastle		= '1 encounter | martial weapon | meleeranged weapon | dex vs ref ! 2W+Dex ! crossbow,lightblade,sling';
  power.Rogue.PositioningStrike	= '1 encounter | martial weapon | melee weapon | dex vs will ! 1W+dex';
  power.Rogue.TorturousStrike	= {
    summary : '1 encounter | martial weapon | melee weapon | dex vs ac ! 2W+dex',
    resetPower : function(power) { if (this == power && this.char.features.BrutalScoundrel) power.rules.hit_damage.addBonus('strM', this, 'system_power'); }
  }
  //
  power.Rogue.BlindingBarrage	= '1 daily | martial weapon | blast 3 /allvise | dex vs ac ! 2W+dex ! crossbow,lightblade,sling';
  power.Rogue.EasyTarget	= '1 daily | martial weapon | meleeranged weapon | dex vs ac ! 2W+dex ! crossbow,lightblade,sling';
  power.Rogue.TrickStrike	= '1 daily | martial weapon | meleetanded weapon | dex vs ac ! 3W+dex ! crossbow,lightblade,sling';
  //
  power.Rogue.FleetingGhost		= {
    summary : 'utility 2 atwill | martial | move personal',
    validate : function(chr) { return chr.trainedSkills.stealth >= chargen.LIST.SELECTED; }
  }
  power.Rogue.GreatLeap		= {
    summary : 'utility 2 atwill | martial | move personal',
    validate : function(chr) { return chr.trainedSkills.athletics >= chargen.LIST.SELECTED; }
  }
  power.Rogue.MasterOfDeceit		= {
    summary : 'utility 2 encounter | martial | free personal',
    validate : function(chr) { return chr.trainedSkills.bluff >= chargen.LIST.SELECTED; }
  }
  power.Rogue.QuickFingers		= {
    summary : 'utility 2 encounter | martial | minor personal',
    validate : function(chr) { return chr.trainedSkills.thievery >= chargen.LIST.SELECTED; }
  }
  power.Rogue.Tumble		= {
    summary : 'utility 2 encounter | martial | move personal',
    validate : function(chr) { return chr.trainedSkills.acrobatics >= chargen.LIST.SELECTED; }
  }
  //
  power.Rogue.BaitAndSwitch		= {
    summary	: '3 encounter | martial weapon | melee weapon | dex vs will ! 2W+dex ! lightblade',
    resetPower : function(power) { if (power == this && chr.features.ArtfulDodger) {
        let num = chargen.Rule.getFirstNumber(this.rules.hit);
        num.removeBonus('rule_part1', '')
        num.addBonus('chaMod', 'rule_part2');
    } }
  }
  power.Rogue.SetupStrike		= '3 encounter | martial weapon | melee weapon | dex vs ac ! 2W+dex ! lightblade';
  power.Rogue.ToppleOver		= {
    summary	: '3 encounter | martial weapon | melee weapon | dex vs ac ! 1W+dex ! lightblade',
    resetPower : function(power) { if (power == this && chr.features.BrutalScoundrel) this.rules.attack.addBonus('strM', 'rule_part2'); }
  }
  power.Rogue.TrickstersBlade	= '3 encounter | martial weapon | meleeranged weapon | dex vs ac ! 2W+dex ! crossbow,lightblade,sling';
  // Rogue attack 5
  power.Rogue.CleverRiposte = '5 daily | martial weapon | melee weapon | dex vs ac ! 2W+dex ! lightblade';
  power.Rogue.DeepCut = '5 daily | martial weapon | melee weapon | dex vs fort ! 2W+dex ! lightblade';
  power.Rogue.WalkingWounded = '5 daily | martial meapon | meleeranged weapon | dex vs fort ! 2W+dex ! crossbow,lightblade,sling';
  // Rogue utility 6
  power.Rogue.Chameleon = 'utility 6 atwill | martial | interrupt personal';
  power.Rogue.IgnobleEscape = 'utility 6  encounter | martial | move person';
  power.Rogue.MobMentality = 'utility 6 encounter | martial | burst 10 /ualla';
  power.Rogue.NimbleClimb = 'utility 6 atwill | martial | move personal';
  power.Rogue.SlipperyMind = 'utility 6 encounter | martial | interrupt personal';
  // Rogue Attack 7
  power.Rogue.CloudOfSteel = '7 encounter | martial weapon | blast 5 /allvise | dex vs ac ! 1W+dex ! crossbow,lightblade,sling';
  power.Rogue.ImperilingStrike = {
    summary : '7 encounter | martial weapon | melee weapon | dex vs fort ! 1W+dex ! lightblade',
    resetPower  : function(power) { if (this.char && this.char.features.BrutalScoundrel) chargen.Rule.getFirstNumber(this.rules.hit).addBonus('strM', this); }
  }
  power.Rogue.RoguesLuck = {
    summary : '7 encounter | martial weapon | meleeranged weapon | dex vs ac ! 2W+dex ! crossbow,lightblade,sling !! ! dex vs ac ! 1W+dex',
    resetPower  : function(power) { if (this.char && this.char.features.ArtfulDodger) this.rules.attack2.addBonus('chaM'); }
  }
  power.Rogue.SandInTheEyes = '7 encounter | martial weapon | melee weapon | dex vs ref ! 1W+dex ! lightblade';
  // Rogue Attack 9
  power.Rogue.CrimsonEdge = '9 daily | martial weapon | melee weapon | dex vs fort ! 2W+dex ! lightblade';
  power.Rogue.DeadlyPositioning = '9 daily | martial weapon | melee 1 | dex vs ac ! 3W+dex ! lightblade';
  power.Rogue.Knockout = '9 daily | martial weapon | melee weapon |  dex vs fort ! 2W+dex ! lightblade';
  //Utility 10
  power.Rogue.CertainFreedom = {
    summary	: 'utility 10 daily | martial | move personal',
    validate : function(chr) { return chr.trainedSkills.acrobatics >= chargen.LIST.SELECTED; }
  }
  power.Rogue.CloseQuarters = {
    summary	: 'utility 10 daily | martial | move personal',
    validate : function(chr) { return chr.trainedSkills.acrobatics >= chargen.LIST.SELECTED; }
  }
  power.Rogue.DangerousTheft = {
    summary	: 'utility 10 encounter | martial | free personal',
    validate : function(chr) { return chr.trainedSkills.thievery >= chargen.LIST.SELECTED; }
  }
  power.Rogue.ShadowStride = {
    summary	: 'utility 10 atwill | martial | move personal',
    validate : function(chr) { return chr.trainedSkills.stealth >= chargen.LIST.SELECTED; }
  }



  power.Warlock = {};
  //
  power.Warlock.WarlocksCurse		= 'feature atwill | | minor /nearvise';
  power.Warlock.EldritchBlast		= {
    summary : '1 atwill | arcane implement | ranged 10 | cha vs ref ! {{1+chr.counts.epic+"d10";||Math.max(chr.chaM,chr.comM);|chaM\u00A0or\u00A0conM||idr}}',
    get attack() { if (this.char) return this.char.conM >= this.char.chaM ? 'con' : 'str';  else return text.str + '/' + text.con; },
    updateAttacks : function(chr) { chr.attacks.push(this); }
  }
  power.Warlock.DireRadiance		= '1 atwill | arcane fear radiant implement | ranged 10 | con vs fort ! {{1+chr.counts.epic+"d6";||conM||idr}}';
  power.Warlock.EyeBite				= '1 atwill | arcane charm psychic implement | ranged 10 | cha vs will ! {{1+chr.counts.epic+"d6";||chaM||idr}}';
  power.Warlock.HellishRebuke		= '1 atwill | arcane fire implement | ranged 10 | con vs ref ! {{1+chr.counts.epic+"d6";||conM||idr}}';
  //
  power.Warlock.DiabolicGrasp		= '1 encounter | arcane implement | ranged 10 | con vs fort ! 2d8+con';
  power.Warlock.DreadfulWord			= {
    summary: '1 encounter | arcane fear psychic implement | ranged 5 | cha vs will ! 2d8+cha',
    resetPower : function(power) { if (power == this && chr.features.StarPact && chr.intM > 0) chargen.Rule.getFirstNumber(this.rules.hit).addBonus('intMod', this); }
  };
  power.Warlock.VampiricEmbrace			= {
    summary : '1 encounter | arcane necrotic implement | ranged 5 | con vs will ! 2d8+con',
    resetPower : function(power) { if (power == this && chr.features.InfernalPact && chr.intM > 0) chargen.Rule.getFirstNumber(this.rules.hit).addBonus('intMod', this); }
  };
  power.Warlock.Witchfire			= {
    summary : '1 encounter | arcane fire implement | ranged 10 | cha vs ref ! 2d6+cha',
    resetPower : function(power) { if (power == this && chr.features.FeyPact) {
        let num = chargen.Rule.getFirstNumber(this.rules.hit);
        num.removeBonus('rule_part1', '')
        num.addBonus(2, 'rule_part1');
        num.addBonus('intMod', 'rule_part2');
    } }
  };
  //
  power.Warlock.ArmorOfAgathys		= '1 daily | arcane cold | personal';
  power.Warlock.CurseOfTheDarkDream	= '1 daily | arcane charm implement psychic | ranged 10 | cha vs ref ! 3d8+cha';
  power.Warlock.DreadStar			= '1 daily | arcane fear radiant implement | ranged 10 | cha vs will ! 3d6+cha';
  power.Warlock.FlamesOfPhlegethos	= '1 daily | arcane fire implement | ranged 10 | con vs ref ! 3d10+con';
  //
  power.Warlock.BeguilingTongue		= 'utility 2 encounter | arcane | minor personal';
  power.Warlock.EtherealStride		= 'utility 2 encounter | arcane teleportation | move personal';
  power.Warlock.FiendishResilience	= 'utility 2 daily | arcane | minor personal';
  power.Warlock.ShadowVeil			= 'utility 2 encounter | arcane illusion | minor personal';
  //
  power.Warlock.EldritchRain		= {
    summary : '3 encounter | arcane implement | ranged 10 /12in5 | cha vs ref ! 1d10+cha ',
    resetPower : function(power) { if (power == this && chr.features.FeyPact && chr.intM > 0) this.rules.hit_damage.addBonus('intM', this, 'system_power'); }
  };
  power.Warlock.FieryBolt			= {
    summary : '3 encounter | arcane fire implement | ranged 10 | con vs ref ! 3d6+con ',
    resetPower : function(power) { if (power == this && chr.features.InfernalPact && chr.intM > 0) chargen.Rule.getFirstNumber(this.rules.hit).addBonus('intMod', this, 'system_power'); }
  };
  power.Warlock.FrigidDarkness		= '3 encounter | arcane cold fear implement | ranged 10 | con vs fort ! 2d8+con';
  power.Warlock.OtherwindStride		= {
    summary : '3 encounter | arcane implement teleportation | burst 1 | cha vs fort ! 1d8+cha ',
    resetPower : function(power) { if (power == this && chr.features.FeyPact && chr.intM > 0) chargen.Rule.getFirstNumber(this.rules.effect).addBonus('intMod', this, 'system_power'); }
  };
  // warlock attack 5
  power.Warlock.AvernianEruption = '5 daily | arcane fire implement | burst 1 in 10 | con vs ref ! 2d10+con';
  power.Warlock.CrownOfMadness = '5 daily | arcane charm implement psychic | ranged 10 | cha vs will ! 2d6+cha';
  power.Warlock.CurseOfTheBloodyFangs = '5 daily | arcane implement | ranged 10 | cha vs ac ! 2d10+cha';
  power.Warlock.HungerOfHadar = '5 daily | arcane implement necrotic zone | burst 1 in 10 | ! 2d10+cha !! /all ! con vs fort ! 1d6+con';
  //
  power.Warlock.DarkOnesOwnLuck = 'utility 6 daily | arcane | free personal';
  power.Warlock.FeySwitch = 'utility 6 encounter | arcane teleportaion | move ranged 10 /un1a';
  power.Warlock.ShroudOfBlackSteel = 'utility 6 daily | arcane polymorph | minor personal';
  power.Warlock.SpiderClimb = 'utility 6 encounter | arcane | move personal';
  // Warlock Attack 7
  power.Warlock.HowlOfDoom = {
    summary : '7 encounter | arcane fear implement thunder | blast 3 | con vs fort ! 2d6+con ',
    resetPower : function(power) { if (power == this && chr.features.InfernalPact && chr.intM > 0) {
      let num = chargen.Rule.getFirstNumber(this.rules.hit);
      num.removeBonus('rule_part1', '')
      num.addBonus(1, 'rule_part1');
      num.addBonus('intMod', 'rule_part2');
    } }
  };
  power.Warlock.InfernalMoonCurse = {
    summary : '7 encounter | arcane implement poison | ranged 10 | con vs fort ! 2d8+con ',
    resetPower : function(power) { if (power == this && chr.features.InfernalPact && chr.intM >= 0) this.rules.hit_damage.addBonus('intM', this); }
  };
  power.Warlock.MireTheMind = '7 encounter | arcane illusion implement psychic | ranged 10 | cha vs will ! 1d10+cha';
  power.Warlock.SignOfIllOmen = '7 encounter | arcane implement | ranged 10 | cha vs will ! 2d6+cha';
  // Warlock Attack 9
  power.Warlock.CurseOfTheBlackFrost = '9 daily | arcane cold implement | ranged 10 | cha vs ref ! 2d8+cha';
  power.Warlock.IronSpikeOfDis = '9 daily | arcane implement | ranged 10 | con vs ref ! 3d10+con';
  power.Warlock.SummonsOfKhirad = '9 daily | arcane implement psychic teleportaion | ranged 10 | con vs will ! 2d10+con';
  power.Warlock.ThiefOfFiveFates = '9 daily | arcane implement | ranged 10 | cha vs will';
  //Utility 10
  power.Warlock.AmbassadorImp = {
    summary : 'utility 10 daily | arcane conjuration | ranged',
    get range() { return this.text.range; } // TODO : Should we make this auto? And target too
  }
  power.Warlock.ShadowForm = 'utility 10 daily | arcane polymorph | minor personal';
  power.Warlock.ShieldingShades = 'utility 10 daily | arcane | reaction personal';
  power.Warlock.WarlocksLeap = 'utility 10 daily | arcane teleportation | move personal';


  power.Warlord = {};
  power.Warlord.InspiringWord		= {
    summary : 'utility feature encounter | martial healing | minor burst /u1a',
    range : '{{5+chr.counts.tier*5;}}'
  };
  //
  power.Warlord.CommandersStrike	= '1 atwill | martial weapon | melee weapon';
  power.Warlord.FuriousSmash		= '1 atwill | martial weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  power.Warlord.VipersStrike		= '1 atwill | martial weapon | melee weapon | str vs fort ! +str';
  power.Warlord.WolfPackTactics		= '1 atwill | martial weapon | melee weapon | str vs ac ! {{1+chr.counts.epic+"W";||strM||wdr}}';
  //
  power.Warlord.GuardingAttack		= {
    summary : '1 encounter | martial weapon | melee weapon | str vs ac ! 2W+str',
    resetPower : function(power) { if (power == this && chr.features.InspiringPresence && chr.chaM > 0) {
      let num = chargen.Rule.getFirstNumber(this.rules.hit);
      num.removeBonus('rule_part1', '')
      num.addBonus(1, 'rule_part1');
      num.addBonus('chaMod', 'rule_part2');
    } }
  };
  power.Warlord.HammerAndAnvil		= '1 encounter | martial weapon | melee weapon | str vs ref ! 2W+str';
  power.Warlord.LeafOnTheWind		= '1 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Warlord.WarlordsFavor		= {
    summary : '1 encounter | martial weapon | melee weapon | str vs ac ! 2W+str',
    resetPower : function(power) { if (power == this && chr.features.TacticalPresence && chr.intM > 0) {
      let num = chargen.Rule.getFirstNumber(this.rules.hit);
      num.removeBonus('rule_part1', '')
      num.addBonus('intMod', 'rule_part2');
    } }
  }
  //
  power.Warlord.BastionOfDefense	= '1 daily | martial weapon | melee weapon | str vs ac ! 3W+str';
  power.Warlord.LeadTheAttack		= '1 daily | martial weapon | melee weapon | str vs ac ! 3W+str';
  power.Warlord.PinTheFoe			= '1 daily | martial weapon | melee weapon | str vs ac ! 3W+str';
  power.Warlord.WhiteRavenOnslaught	= '1 daily | martial weapon | melee weapon | str vs ac ! 3W+str';
  //
  power.Warlord.AidTheInjured		= 'utility 2 encounter | martial healing | touch /u1a';
  power.Warlord.CrescendoOfViolence	= 'utility 2 encounter | martial | reaction ranged 5';
  power.Warlord.KnightsMove			= 'utility 2 encounter | martial | move ranged 10 /1a';
  power.Warlord.ShakeItOff			= 'utility 2 encounter | martial | minor ranged 10 /u1a';
  // Encounter 3
  power.Warlord.HoldTheLine			= '3 encounter | martial weapon | melee weapon | str vs ac ! 1W+str';
  power.Warlord.InspiringWarCry		= '3 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Warlord.SteelMonsoon		= {
    summary : '3 encounter | martial weapon | melee weapon | str vs ac ! 2W+str ',
    resetPower : function(power) { if (power == this && chr.features.TacticalPresence && chr.intM > 0) {
      let num = chargen.Rule.getFirstNumber(this.rules.hit);
      num.removeBonus('rule_part1', '')
      num.addBonus('intMod', 'rule_part1');
    } }
  };
  power.Warlord.WarlordsStrike		= {
    summary : '3 encounter | martial weapon | melee weapon | str vs ac ! 2W+str ',
    resetPower : function(power) { if (power == this && chr.features.InspiringPresence && chr.chaM > 0) {
      let num = chargen.Rule.getFirstNumber(this.rules.hit);
      num.removeBonus('rule_part1', '')
      num.addBonus('1', 'rule_part1');
      num.addBonus('chaMod', 'rule_part2');
    } }
  };
  //
  power.Warlord.StandTheFallen = '5 daily | healing martial weapon | melee weapon | str vs ac ! 3W+str';
  power.Warlord.TurningPoint = '5 daily | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Warlord.VillainsNightmare = '5 daily | martial weapon | melee weapon | str vs ref ! 3W+str';
  //
  power.Warlord.GuideTheCharge = 'utility 6 encounter | martial | interrupt ranged 10';
  power.Warlord.InspiringReaction = 'utility 6 encounter | healing martial | reaction melee touch';
  power.Warlord.QuickStep = 'utility 6 daily | martial | minor ranged 10 /1a';
  //
  power.Warlord.LionsRoar = {
    summary	: '7 encounter | healing martial weapon | melee weapon | str vs ac ! 2W+str ',
    resetPower : function(power) {
      if (power == this && this.char && this.char.features.InspiringPresence)
        chargen.Rule.getFirstNumber(this.rules.effect).addBonus('chaM', chr.features.InspiringPresence.selection);
    }
  }
  power.Warlord.SunderArmor = '7 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  power.Warlord.SurpriseAttack = '7 encounter | martial weapon | melee weapon | str vs ac ! 1W+str';
  power.Warlord.SurroundFoe = '7 encounter | martial weapon | melee weapon | str vs ac ! 2W+str';
  //
  power.Warlord.IronDragonCharge = '9 daily | martial weapon | melee weapon | str vs ac ! 3W+str';
  power.Warlord.KnockThemDown = '9 daily | martial weapon | melee weapon | str vs ac ! 3W+str';
  power.Warlord.WhiteRavenStrike = '9 daily | martial weapon | melee weapon | str vs ac ! 3W+str';
  //
  power.Warlord.DefensiveRally = 'utility 10 daily | healing martial | burst 5 /alla';
  power.Warlord.EaseSuffering = 'utility 10 daily | martial | minor personal';
  power.Warlord.TacticalShift = 'utility 10 daily | martial | interrupt ranged 10';


  power.Wizard = {};
  power.Wizard.GhostSound		= 'utility feature atwill | arcane | ranged 10';
  power.Wizard.Light			= 'utility feature atwill | arcane | ranged 5';
  power.Wizard.MageHand			= 'utility feature atwill | arcane | ranged 5';
  power.Wizard.Prestidigitation		= 'utility feature atwill | arcane | ranged 2';
  //
  power.Wizard.CloudOfDaggers	= '1 atwill | arcane force implement | 1 in 10 /all | int vs ref ! {{1+chr.counts.epic*1+"d6";||intM||idr}}';
  power.Wizard.MagicMissile		= {
    summary : '1 atwill | arcane force implement | ranged 20 | int vs ref ! {{2+chr.counts.epic*2+"d4";||intM||idr}}',
    updateAttacks : function(chr) { chr.attacks.push(this); }
  };
  power.Wizard.RayOfFrost		= '1 atwill | arcane cold implement | ranged 10 | int vs fort ! {{1+chr.counts.epic+"d6";||intM||idr}}';
  power.Wizard.ScorchingBurst	= '1 atwill | arcane fire implement | burst 1 in 10 | int vs ref ! {{1+chr.counts.epic+"d6";||intM||idr}}';
  power.Wizard.Thunderwave		= '1 atwill | arcane thunder implement | blast 3 | int vs fort ! {{1+chr.counts.epic+"d6";||intM||idr}}';
  //
  power.Wizard.BurningHands		= '1 encounter | arcane fire implement | blast 5 | int vs ref ! 2d6+int';
  power.Wizard.ChillStrike		= '1 encounter | arcane cold implement | ranged 10 | int vs fort ! 2d8+int';
  power.Wizard.ForceOrb			= '1 encounter | arcane force implement | ranged 20 | int vs ref ! 2d8+int !! /allsecadj ! int vs ref ! d10+int';
  power.Wizard.IcyTerrain		= '1 encounter | arcane cold implement | burst 1 in 10 | int vs ref ! d6+int';
  power.Wizard.RayOfEnfeeblement		= '1 encounter | arcane necrotic implement | ranged 10 | int vs fort ! d10+int';
  //
  power.Wizard.AcidArrow		= '1 daily | arcane acid implement | ranged 20 | int vs ref ! 2d8+int';
  power.Wizard.FlamingSphere	= '1 daily | arcane fire conjuration implement | ranged 10 | int vs ref ! 2d6+int';
  power.Wizard.FreezingCloud	= '1 daily | arcane cold implement | burst 2 in 10 | int vs fort ! 1d8+int';
  power.Wizard.Sleep			= '1 daily | arcane implement sleep | burst 2 in 20 | int vs will';
  //
  power.Wizard.ExpeditiousRetreat	= 'utility 2 daily | arcane | move personal';
  power.Wizard.FeatherFall		= 'utility 2 daily | arcane | free /u1c';
  power.Wizard.Jump				= 'utility 2 encounter | arcane | move /u1c';
  power.Wizard.Shield			= 'utility 2 encounter | arcane force | move personal';
  //
  power.Wizard.ColorSpray		= '3 encounter | arcane implement radiant | blast 5 | int vs will ! 1d6+int';
  power.Wizard.FireShroud		= '3 encounter | arcane fire implement | burst 3 /alle | int vs fort ! 1d8+int';
  power.Wizard.IcyRays			= '3 encounter | arcane cold implement | ranged 10 /12 | int vs Ref ! 1d10+int';
  power.Wizard.ShockSphere		= '3 encounter | arcane implement lightning | burst 2 in 10 | int vs ref ! 2d6+int';
  //
  power.Wizard.BigbysIcyGrasp	= '5 daily | arcane cold conjuration implement | ranged 20 | int vs ref ! 2d8+int';
  power.Wizard.Fireball			= '5 daily | arcane fire implement | burst 3 in 20 | int vs ref ! 3d6+int';
  power.Wizard.StinkingCloud	= '5 daily | arcane implement poison zone | burst 2 in 20 | int vs fort ! 1d10+int';
  power.Wizard.Web				= '5 daily | arcane implement zone | burst 2 in 20 | int vs ref';
  //
  power.Wizard.DimensionDoor = 'utility 6 daily | arcane teleportation | move personal';
  power.Wizard.DisguiseSelf = 'utility 6 daily | arcane illusion | minor personal';
  power.Wizard.DispelMagic = 'utility 6 daily | arcane | ranged 10 /1conjzone | int vs will';
  power.Wizard.Invisibility = 'utility 6 daily | arcane illusion | ranged 10 /u1c';
  power.Wizard.Levitate = 'utility 6 daily | arcane | move personal';
  power.Wizard.WallOfFog = 'utility 6 daily | arcane conjuration | wall 8 in 10';
  //
  power.Wizard.FireBurst = '7 encounter | arcane fire implement | burst 2 in 20 | int vs ref ! 3d6+int';
  power.Wizard.LightningBolt = '7 encounter | arcane implement lightning | ranged 10 | int vs ref ! 2d6+int';
  power.Wizard.SpectralRam = '7 encounter | arcane force implement | ranged 10 | int vs fort ! 2d10+int';
  power.Wizard.WintersWrath = '7 encounter | arcane cold implement | burst 2 in 10 | int vs frot ! 2d8+int';
  //
  power.Wizard.IceStorm = '9 daily | arcane cold implement zone | burst 3 in 20 | int vs fort ! 2d8+int';
  power.Wizard.LightningSerpent = '9 daily | arcane implement lightning posion | ranged 10 | int vs ref ! 2d12+int';
  power.Wizard.MordenkainensSword = '9 daily | arcane conjuration force implement | ranged 10 | int vs ref ! 1d10+int';
  power.Wizard.WallOfFire = '9 daily | arcane conjuration fire implement | wall 8 in 10 | ! 1d6+int';
  //Utility 10
  power.Wizard.ArcaneGate = 'utility 10 daily | arcane teleportation | minor ranged 20 /2freesq';
  power.Wizard.Blur = 'utility 10 daily | arcane illusion | minor personal';
  power.Wizard.MirrorImage = 'utiltiy 10 daily | arcane illusion | minor personal';
  power.Wizard.Resistance = 'utility 10 daily | arcane | minor ranged 10 /u1c';

  power.Swordmage = {};
  power.Swordmage.AegisOfAssult = 'feature atwill | arcane teleportation | minor burst 2 /1';
  power.Swordmage.AegisOfShielding  = 'feature atwill | arcane | minor burst 2 /1';
  power.Swordmage.BoomingBlade  = '1 atwill | arcane thunder weapon | melee weapon | int vs ac ! {{1+chr.counts.epic+"W";||intM||wdr}}';
  power.Swordmage.GreenflameBlade = '1 atwill | arcane fire weapon | melee weapon | int vs ac ! {{1+chr.counts.epic+"W";||intM||wdr}}';
  power.Swordmage.LightningLure = '1 atwill | arcane lightning implement | ranged 3 | int vs ac ! {{1+chr.counts.epic+"d6";||intM||idr}}';
  power.Swordmage.SwordBurst  = '1 atwill | arcane force implement | burst 1 | int vs ref ! {{1+chr.counts.epic+"d6";||intM||idr}}';
  //
  power.Swordmage.ChillingBlow  = '1 encounter | arcane cold weapon | melee weapon | int vs ac ! 1W+int';
  power.Swordmage.FlameCyclone  = '1 encounter | arcane fire implement | blast 3 | int vs ref ! 1d8+int+str';
  //
  power.Swordmage.BurningBlade  = '1 daily | arcane fire weapon | melee weapon | int vs ac ! 2W+int';
  power.Swordmage.FrostBacklash  = '1 daily | arcane cold weapon | interrupt melee weapon /trige | int vs ac ! 3W+int';
  //
  power.Swordmage.DimensionalWarp  = 'utility 2 encounter | arcane teleportation | minor burst 3 /un1ao2a';
  power.Swordmage.EldritchSpeed  = 'utility 2 encounter | arcane | no personal';



  power.Artificer = {};
  power.Artificer.RestorativeFormula		= {
    summary : 'utility feature encounter | arcane healing | minor burst /ualla',
    range : '{{5+chr.counts.tier*5;}}'
  };
  power.Artificer.CurativeAdmixture = 'utility feature encounter | arcane | minor burst /ualla';
  power.Artificer.RepairObject = 'feature encounter | arcane healing | minor melee touch /1o';
  // At Will
  power.Artificer.ThunderingArmor = '1 atwill | arcane implement thunder | ranged 10 !';
  power.Artificer.AggravatingForce = '1 atwill | arcane force weapon | ranged weapon !';
  // Encounter 1
  power.Artificer.SpikeWire = '1 encounter | arcane force weapon | burst 1 in weapon range | int vs fort ! 1W+int';
  power.Artificer.ShieldingCube = '1 encounter | arcane artifice force implement | ranged 10 | int vs ref ! 1d8+int';
  // Daily 1
  power.Artificer.Lifetap = '1 daily | arcane implement | ranged 10 | int vs ref ! 2d10+int';
  power.Artificer.CausticRampart = '1 daily | acid arcane conjuration implement | wall 5 in 10';
  // Utility 2
  power.Artificer.RestorativeInfusion = 'utility 2 daily | arcane | ranged 10 /u1a';
  power.Artificer.ArcaneSpringboard = 'utility 2 daily | arcane artifice | ranged 10';
  // Encounter 3
  power.Artificer.AlteredLuck = '3 encounter | arcane implement | burst 2 in 10 | int vs will';
  power.Artificer.FieryInfusion = '3 encounter | arcane fire weapon | burst 1 in weapon range | int vs ref ! 1W+int ! ranged';
  // Daily 5
  power.Artificer.PredatoryShards = '5 daily | arcane force weapon zone | burst 1 in weapon range | int vs ac ! 2W+int ! ranged';
  power.Artificer.DancingWeapon = '5 daily | arcane artifice implement weapon | ranged 10 | int vs ac ! 1W+int ! melee';
  // Utility 6
  power.Artificer.RegenerationInfusion = 'utility 6 daily | arcane healing | ranged 10 /*';
  //Target: You if you're bloodied or one bloodied ally
  power.Artificer.PhantomStructure = 'utility 6 daily | arcane conjuration | ranged 5';
  // Encounter 7
  power.Artificer.GaleForceInfusion = '7 encounter | arcane implement | burst 2 in 10 | int vs ref ! 1d10+int';
  power.Artificer.RunicResistance = '7 encounter | arcane implement acid cold fire lightning | burst 1 in 10 | int vs ref ! 2d6+int';
  //这里，Encounter arcane, implement; acid, Cold, Fire,  or lightning，可能需要改一下。
  // Daily 9
  power.Artificer.LightningMotes = '9 daily | arcane implement lightning | burst 3 | int vs ref ! 2d10+int';
  power.Artificer.BrittleskinInfusion = '9 daily | arcane weapon | ranged weapon | int vs ac ! 2W+int';
  // Utility 10
  power.Artificer.HealingFigurine = 'utility 10 daily | arcane artifice healing | ranged 10';
  power.Artificer.SlickConcoction = 'utility 10 encounter | arcane | move ranged 5 /1a';

}