#===============================================================================
# 
# Yanfly Engine Melody - Enemy Levels
# Last Date Updated: 2010.05.31
# Level: Normal, Hard
# 
# RPG's with enemies that level up with the party enforces the player to stay
# on their toes the whole time. This is both a good and bad thing as it can
# cause the player to stay alert, but can also cause the player to meet some
# roadblocks. This script will not only provide enemies the ability to level up
# but also allow the script's user to go around these roadblocks using various
# tags to limit or slow down the rate of growth across all enemies.
# 
#===============================================================================
# Updates
# -----------------------------------------------------------------------------
# o 2010.05.31 - Converted to Yanfly Engine Melody.
#===============================================================================
# Instructions
# -----------------------------------------------------------------------------
# To install this script, open up your script editor and copy/paste this script
# to an open slot below ▼ Materials but above ▼ Main. Remember to save.
# 
# -----------------------------------------------------------------------------
# Enemy Tags - Insert the following tags into Enemy noteboxes.
# -----------------------------------------------------------------------------
# <min level: x> 
# <max level: x>
# This will adjust the minimum and maximum levels for the enemy. By default,
# the minimum level is 1 and the maximum level is whatever is set below in the
# module below as MAX_LEVEL.
# 
# <set level: x>
# This will set the enemy's level to exactly x. It a sense, this is just the
# usage of both the min and max level tags together as the same value.
# 
# <level type: x>
# Choosing a value from 0 to 4, you can adjust the different leveling rulesets
# for the enemy. View the DEFAULT_LEVEL_TYPE module option to see what kinds of
# rules there are for level types.
# 
# <level bonus: +x> or <level bonux: -x>
# This will place the enemy x levels above or below the base level when set. If
# it has a bonus of +10, it will be 10 levels higher than whatever the normal
# ruleset set for the enemy is.
# 
# <level random: x>
# This will give the level a random flunctuation in either direction. Set this
# value to 0 if you don't wish to use it. Adjust RANDOM_FLUCTUATION inside the
# module to change the default fluctuation value.
# 
# <level state x: y> or <level states x: y,y>
# At level x and higher, the enemy will have the auto states y applied to it. 
# Use multiple of these tags to designate different levels and the states the
# enemy will gain at those levels.
# 
# <stat: +x per level>  or <stat: -x per level>
# <stat: +x% per level> or <stat: -x% per level>
# This will raise or lower the stat by x or x% per level (depending on the tag
# used). This will override the default growth settings found inside the module
# hash called DEFAULT_GROWTH. You may replace stat with:
# maxhp, maxmp, atk, def, spi, res, dex, agi, gold, exp
# 
# <base stat: x>
# This will allow you to manually adjust the base stat to x value if you want a
# value higher than 999. Note that this won't mean much if you don't have a stat
# limit breaker script installed like KGC Limit Breaker. Replace stat with:
# maxhp, maxmp, atk, def, spi, agi
# 
# <phrase trait at level: x>
# This will give the enemy a particular trait at level x or higher. Use more of
# these tags to give enemies different traits at different levels. Replace the
# phrase with one of the following:
#   super guard  - Gives the enemy super guard properties.
#   fast attack  - Gives the enemy fast attack properties.
#   dual attack  - Gives the enemy dual attack properties.
#   prevent crit - Prevents the enemy from taking critical hits.
#   half mp cost - Enemy skills will use only half MP.
# 
# <doppelganger: x>
# This creates a doppelganger of the actor x in terms of levels and stats. The
# actors skills and such will not be carried over as enemies use an AI set for
# their skills and does not translate over that easily.
# 
# -----------------------------------------------------------------------------
# Skill and Item Tags - Insert the following tags into Skill or Item noteboxes.
# -----------------------------------------------------------------------------
# <enemy level: +x> or <enemy level: -x>
# This causes the enemy to raise or drop x levels depending on the tag used.
# The new level will readjust the enemy's stats (including HP and MP).
# 
# <enemy level reset>
# This resets the enemy's level back to the typical range it should be plus or
# minus any level fluctuations it was given. This occurs before enemy level +
# and enemy level - tags.
#===============================================================================

$imported = {} if $imported == nil
$imported["EnemyLevels"] = true

module YEM
  module ENEMY_LEVEL
    
    #===========================================================================
    # Section I. Basic Settings
    # --------------------------------------------------------------------------
    # These settings adjust the basic rules that govern the whole leveling
    # system for enemies. Adjust them accordingly.
    #===========================================================================
    
    # This is how the level text will appear whenever enemy levels are shown.
    LEVEL_TEXT = "LV%d %s"
    
    # This is the maximum level your enemies can achieve. They cannot go higher
    # no exceptions. Adjust this accordingly to fit your game.
    MAX_LEVEL = 99
    
    # These two variables adjust the enemy levels by a set amount and a percent
    # amount respectively. Set amounts will adjust the levels of all enemies by
    # a set number while percentile amounts will adjust the levels by a percent
    # number out of 100. Set values are applied after percentile values.
    SET_VARIABLE = 31
    PER_VARIABLE = 32
    
    # These settings adjust the default growth rates (not the base stat formula)
    # for each stat. These are the values that will exist for each enemy unless
    # defined otherwise by the tags inside their noteboxes.
    DEFAULT_GROWTH ={
    # Stat   => [ +Set, Per%]
      :maxhp => [   50,   15],
      :maxmp => [   10,   10],
      :atk   => [    5,    5],
      :def   => [    5,    5],
      :spi   => [    5,    5],
      :res   => [    5,    5],
      :dex   => [    5,    5],
      :agi   => [    5,    5],
      :gold  => [  100,   15],
      :exp   => [   25,   15],
    } # Do not remove this.
    
    # Default level calculations for your enemies will be adjusted as such.
    # Type 0 - Lowest level of all actors. (not recommended)
    # Type 1 - Lowest level in the Player Party
    # Type 2 - Average level of the Player Party.
    # Type 3 - Highest level of the Player Party.
    # Type 4 - Highest level of all actors.
    DEFAULT_LEVEL_TYPE = 4
    
    # If you want your enemies to have random +/- levels of some degree, change
    # this number to something other than 0. This is the default value.
    RANDOM_FLUCTUATION = 2
    
    #===========================================================================
    # Section II. Formula Settings
    # --------------------------------------------------------------------------
    # These are the various base formulas made and set out for each of the base
    # stats. Adjust them as you see fit but only if you know what you're doing.
    # 
    #   base  - The base stat from the enemy database.
    #   per   - Growth rate which has not been yet converted to a percent.
    #   set   - Set growth rate. Modified
    # 
    # Default:   (base * (100 + (level-1) * per)/100) + (set * (level-1))
    #===========================================================================
    
    # The following hash will adjust each of the formulas for each base stat.
    BASE_FORMULAS ={
    # Stat   => "Formula"
      :maxhp => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :maxmp => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :atk   => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :def   => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :spi   => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :res   => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :dex   => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :agi   => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :gold  => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
      :exp   => "(base * (100 + (level-1) * per)/100) + (set * (level-1))",
    } # Do not remove this.
    
    #===========================================================================
    # Section III. Compatibility Settings
    # --------------------------------------------------------------------------
    # These settings are used for outside scripts to enable better functionality
    # and compatibility in regards to them.
    #===========================================================================
    
    # This is the AI boost per level for the YEM AI and Aggro script. If that
    # script is not installed and not updated, this will have no effect.
    AI_LEVEL_BOOST = 0.25
    
  end # ENEMY_LEVEL  
end # YEM

#===============================================================================
# Editting anything past this point may potentially result in causing computer
# damage, incontinence, explosion of user's head, coma, death, and/or halitosis.
# Therefore, edit at your own risk.
#===============================================================================

module YEM
module REGEXP
module USABLEITEM
      
  LEVEL_CHANGE = /<(?:ENEMY LEVEL|enemy level):[ ]([\+\-]\d+)>/i
  LEVEL_RESET  = /<(?:ENEMY LEVEL RESET|enemy level reset)>/i
      
end # USABLEITEM
module ENEMY
      
  MIN_LEVEL = /<(?:MIN_LEVEL|min level|minimum level):[ ](\d+)>/i
  MAX_LEVEL = /<(?:MAX_LEVEL|max level|maximum level):[ ](\d+)>/i
  SET_LEVEL = /<(?:SET_LEVEL|set level|permanent level):[ ](\d+)>/i
      
  LEVEL_TYPE = /<(?:LEVEL_TYPE|level type):[ ](\d+)>/i
  GROWTH_SET = /<(.*):[ ]([\+\-]\d+)[ ](?:PER_LEVEL|per level)>/i
  GROWTH_PER = /<(.*):[ ]([\+\-]\d+)([%％])[ ](?:PER_LEVEL|per level)>/i
  BASE_STAT  = /<(?:BASE|original)[ ](.*):[ ](\d+)>/i
      
  ACTOR_CLONE = /<(?:ACTOR_CLONE|actor clone|doppelganger):[ ](\d+)>/i
  LEVEL_BONUS = /<(?:LEVEL|level):[ ]([\+\-]\d+)>/i
  LEVEL_RAND  = /<(?:LEVEL_RANDOM|level random):[ ](\d+)>/i
  LEVEL_TRAIT = /<(.*)[ ](?:TRAIT AT LEVEL|at level):[ ](\d+)>/i
  LEVEL_STATE = /<(?:LEVEL STATE|level states):[ ](\d+):(\d+(?:\s*,\s*\d+)*)>/i
      
end # ENEMY
end # REGEXP
end # YEM

#===============================================================================
# RPG::BaseItem
#===============================================================================

class RPG::UsableItem < RPG::BaseItem
  
  #--------------------------------------------------------------------------
  # public instance variables
  #--------------------------------------------------------------------------
  attr_accessor :level_change
  attr_accessor :level_reset
  
  #--------------------------------------------------------------------------
  # common cache: yem_cache_baseitem_el
  #--------------------------------------------------------------------------
  def yem_cache_usableitem_el
    return if @cached_usableitem_el; @cached_usableitem_el = true
    @level_change = 0; @level_reset = false
    
    self.note.split(/[\r\n]+/).each { |line|
      case line
      when YEM::REGEXP::USABLEITEM::LEVEL_CHANGE
        @level_change = $1.to_i
      when YEM::REGEXP::USABLEITEM::LEVEL_RESET
        @level_reset = true
      end
    } # end self.note.split
  end # yem_cache_usableitem_el
  
end # RPG::UsableItem

#===============================================================================
# RPG::Enemy
#===============================================================================

class RPG::Enemy
  
  #--------------------------------------------------------------------------
  # new method: min_level
  #--------------------------------------------------------------------------
  attr_accessor :min_level
  attr_accessor :max_level
  attr_accessor :level_type
  attr_accessor :level_bonus
  attr_accessor :level_random
  attr_accessor :level_traits
  attr_accessor :level_states
  attr_accessor :doppelganger
  attr_accessor :growth_set
  attr_accessor :growth_per
  attr_accessor :maxhp
  attr_accessor :maxmp
  attr_accessor :atk
  attr_accessor :def
  attr_accessor :spi
  attr_accessor :agi
  
  #--------------------------------------------------------------------------
  # common cache: yem_cache_enemy_el
  #--------------------------------------------------------------------------
  def yem_cache_enemy_el
    return if @cached_enemy_el; @cached_enemy_el = true
    @level_type = [[YEM::ENEMY_LEVEL::DEFAULT_LEVEL_TYPE, 0].max, 4].min
    @growth_set = {}; @growth_per = {}; @checked_new_base_stats = true
    for item in [:maxhp,:maxmp,:atk,:def,:spi,:res,:dex,:agi,:gold,:exp]
      @growth_set[item] = YEM::ENEMY_LEVEL::DEFAULT_GROWTH[item][0]
      @growth_per[item] = YEM::ENEMY_LEVEL::DEFAULT_GROWTH[item][1]
    end
    @level_bonus = 0; @level_random = YEM::ENEMY_LEVEL::RANDOM_FLUCTUATION
    @level_traits = {}; @min_level = 1; @max_level = YEM::ENEMY_LEVEL::MAX_LEVEL
    @level_states = {}; @doppelganger = 0
    
    self.note.split(/[\r\n]+/).each { |line|
      case line
      #---
      when YEM::REGEXP::ENEMY::MIN_LEVEL
        @min_level = [[$1.to_i, 1].max, YEM::ENEMY_LEVEL::MAX_LEVEL].min
      when YEM::REGEXP::ENEMY::MAX_LEVEL
        @max_level = [[$1.to_i, 1].max, YEM::ENEMY_LEVEL::MAX_LEVEL].min
      when YEM::REGEXP::ENEMY::SET_LEVEL
        @min_level = [[$1.to_i, 1].max, YEM::ENEMY_LEVEL::MAX_LEVEL].min
        @max_level = [[$1.to_i, 1].max, YEM::ENEMY_LEVEL::MAX_LEVEL].min
      #---
      when YEM::REGEXP::ENEMY::LEVEL_TYPE
        @level_type = [[$1.to_i, 0].max, 4].min
      #---
      when YEM::REGEXP::ENEMY::LEVEL_BONUS
        @level_bonus = $1.to_i
      #---
      when YEM::REGEXP::ENEMY::LEVEL_RAND
        @level_random = $1.to_i
      #---
      when YEM::REGEXP::ENEMY::ACTOR_CLONE
        @doppelganger = $1.to_i
      #---
      when YEM::REGEXP::ENEMY::GROWTH_SET
        case $1.upcase
        when "MAXHP"; @growth_set[:maxhp] = $2.to_i
        when "MAXMP"; @growth_set[:maxmp] = $2.to_i
        when "ATK";   @growth_set[:atk] = $2.to_i
        when "DEF";   @growth_set[:def] = $2.to_i
        when "SPI";   @growth_set[:spi] = $2.to_i
        when "RES";   @growth_set[:res] = $2.to_i
        when "DEX";   @growth_set[:dex] = $2.to_i
        when "AGI";   @growth_set[:agi] = $2.to_i
        when "GOLD";  @growth_set[:gold] = $2.to_i
        when "EXP";   @growth_set[:exp] = $2.to_i
        end
      #---
      when YEM::REGEXP::ENEMY::GROWTH_PER
        case $1.upcase
        when "MAXHP"; @growth_per[:maxhp] = $2.to_i
        when "MAXMP"; @growth_per[:maxmp] = $2.to_i
        when "ATK";   @growth_per[:atk] = $2.to_i
        when "DEF";   @growth_per[:def] = $2.to_i
        when "SPI";   @growth_per[:spi] = $2.to_i
        when "RES";   @growth_per[:res] = $2.to_i
        when "DEX";   @growth_per[:dex] = $2.to_i
        when "AGI";   @growth_per[:agi] = $2.to_i
        when "GOLD";  @growth_per[:gold] = $2.to_i
        when "EXP";   @growth_per[:exp] = $2.to_i
        end
      #---
      when YEM::REGEXP::ENEMY::BASE_STAT
        case $1.upcase
        when "MAXHP"; @maxhp = $2.to_i
        when "MAXMP"; @maxmp = $2.to_i
        when "ATK";   @atk = $2.to_i
        when "DEF";   @def = $2.to_i
        when "SPI";   @spi = $2.to_i
        when "AGI";   @agi = $2.to_i
        end
      #---
      when YEM::REGEXP::ENEMY::LEVEL_TRAIT
        case $1.upcase
        when "SUPER GUARD", "SUPERGUARD", "SUPER_GUARD"
          @level_traits[:super_guard] = $2.to_i
        when "FAST ATTACK", "FASTATTACK", "FAST_ATTACK"
          @level_traits[:fast_attack] = $2.to_i
        when "DUAL ATTACK", "DUALATTACK", "DUAL_ATTACK"
          @level_traits[:dual_attack] = $2.to_i
        when "PREVENT CRITICAL", "PREVENT CRIT", "PREVENTCRIT"
          @level_traits[:prevent_critical] = $2.to_i
        when "HALF MP COST", "HALF MP", "HALF_MP_COST"
          @level_traits[:half_mp_cost] = $2.to_i
        end
      #---
      when YEM::REGEXP::ENEMY::LEVEL_STATE
        @level_states[$1.to_i] = [] if @level_states[$1.to_i] == nil
        $2.scan(/\d+/).each { |num| @level_states[$1.to_i] += [num.to_i] }
      #---
      end
    } # end self.note.split
  end # yem_cache_enemy_el
  
end # RPG::Enemy

#===============================================================================
# Scene_Title
#===============================================================================

class Scene_Title < Scene_Base
  
  #--------------------------------------------------------------------------
  # alias method: load_bt_database
  #--------------------------------------------------------------------------
  alias load_bt_database_el load_bt_database unless $@
  def load_bt_database
    load_bt_database_el
    load_el_cache
  end
  
  #--------------------------------------------------------------------------
  # alias method: load_database
  #--------------------------------------------------------------------------
  alias load_database_el load_database unless $@
  def load_database
    load_database_el
    load_el_cache
  end
  
  #--------------------------------------------------------------------------
  # new method: load_el_cache
  #--------------------------------------------------------------------------
  def load_el_cache
    groups = [$data_skills, $data_items, $data_enemies]
    for group in groups
      for obj in group
        next if obj == nil
        obj.yem_cache_usableitem_el if obj.is_a?(RPG::UsableItem)
        obj.yem_cache_enemy_el if obj.is_a?(RPG::Enemy)
      end
    end
  end
  
end # Scene_Title

#===============================================================================
# Game_Battler
#===============================================================================

class Game_Battler
  
  #--------------------------------------------------------------------------
  # alias method: item_effect
  #--------------------------------------------------------------------------
  alias item_effect_el item_effect unless $@
  def item_effect(user, item)
    item_effect_el(user, item)
    if !actor? and !@skipped and !@missed and !@evaded
      self.reset_level 
      self.level += item.level_change
    end
  end
  
  #--------------------------------------------------------------------------
  # alias method: skill_effect
  #--------------------------------------------------------------------------
  alias skill_effect_el skill_effect unless $@
  def skill_effect(user, skill)
    skill_effect_el(user, skill)
    if !actor? and !@skipped and !@missed and !@evaded
      self.reset_level if skill.level_reset
      self.level += skill.level_change
    end
  end
  
end # Game_Battler

#===============================================================================
# Game_Enemy
#===============================================================================

class Game_Enemy < Game_Battler
  
  #--------------------------------------------------------------------------
  # alias method: initialize
  #--------------------------------------------------------------------------
  alias initialize_enemy_el initialize unless $@
  def initialize(index, enemy_id)
    initialize_enemy_el(index, enemy_id)
    create_level
    @hp = maxhp
    @mp = maxmp
  end
  
  #--------------------------------------------------------------------------
  # alias method: transform
  #--------------------------------------------------------------------------
  alias transform_el transform unless $@
  def transform(enemy_id)
    transform_el(enemy_id)
    @base_stats = nil
    create_level
  end
  
  #--------------------------------------------------------------------------
  # new method: reset_level
  #--------------------------------------------------------------------------
  def reset_level
    @base_stats = nil
    create_level
  end
  
  #--------------------------------------------------------------------------
  # new method: create_level
  #--------------------------------------------------------------------------
  def create_level
    @level = nil
    case enemy.level_type
    when 0 # Lowest level of all actors.
      for i in 1..($data_actors.size - 1)
        @level = $game_actors[i].level if @level == nil
        @level = [$game_actors[i].level, @level].min
        break if @level == 1
      end
    when 1 # Lowest level of the party.
      group = $game_party.members
      for actor in group
        @level = actor.level if @level == nil
        @level = [actor.level, @level].min
        break if @level == 1
      end
    when 2 # Average level of the party.
      group = $game_party.members
      @level = 0
      for actor in group; @level += actor.level; end
      @level /= group.size
    when 3 # Highest level of the party.
      group = $game_party.members
      for actor in group
        @level = actor.level if @level == nil
        @level = [actor.level, @level].max
      end
    when 4 # Highest level of all actors.
      for i in 1..($data_actors.size - 1)
        @level = $game_actors[i].level if @level == nil
        @level = [$game_actors[i].level, @level].max
      end
    else # Nothing else.
      @level = 1
    end
    $game_variables[YEM::ENEMY_LEVEL::PER_VARIABLE] = 100 if
      $game_variables[YEM::ENEMY_LEVEL::PER_VARIABLE] <= 0
    @level = @level * $game_variables[YEM::ENEMY_LEVEL::PER_VARIABLE] / 100
    @level += $game_variables[YEM::ENEMY_LEVEL::SET_VARIABLE]
    @level += enemy.level_bonus
    @level += rand(enemy.level_random+1)
    @level -= rand(enemy.level_random+1)
    @level = [[@level, enemy.max_level].min, enemy.min_level].max
    create_doppelganger
  end

  #--------------------------------------------------------------------------
  # new method: level
  #--------------------------------------------------------------------------
  def level
    create_level if @level == nil
    return [[@level, 1].max, YEM::ENEMY_LEVEL::MAX_LEVEL].min
  end
  
  #--------------------------------------------------------------------------
  # new method: level=
  #--------------------------------------------------------------------------
  def level=(value)
    return if value == 0
    return if enemy.doppelganger > 0
    clear_battle_cache if $imported["BattleEngineMelody"]
    last_hp = self.maxhp
    last_mp = self.maxmp
    @level = value
    @base_stats = nil unless enemy.doppelganger > 0
    unless self.dead?
      clear_battle_cache if $imported["BattleEngineMelody"]
      self.hp += self.maxhp - last_hp
      self.mp += self.maxmp - last_mp
    end
  end
  
  #--------------------------------------------------------------------------
  # new method: create_doppelganger
  #--------------------------------------------------------------------------
  def create_doppelganger
    return unless enemy.doppelganger > 0
    actor = $game_actors[enemy.doppelganger]
    return if actor == nil
    @level = actor.level
    @base_stats = {} if @base_stats == nil
    @base_stats[:maxhp]    = actor.base_maxhp
    @base_stats[:maxmp] = actor.base_maxmp
    @base_stats[:atk]   = actor.base_atk
    @base_stats[:def]   = actor.base_def
    @base_stats[:spi]   = actor.base_spi
    @base_stats[:res]   = actor.base_res if $imported["RES Stat"]
    @base_stats[:dex]   = actor.base_dex if $imported["DEX Stat"]
    @base_stats[:agi]   = actor.base_agi
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: base_maxhp
  #--------------------------------------------------------------------------
  def base_maxhp
    @base_stats = {} if @base_stats == nil
    return @base_stats[:maxhp] if @base_stats[:maxhp] != nil
    @boost_maxhp = 0 if @boost_maxhp == nil
    base = enemy.maxhp + @boost_maxhp
    per = enemy.growth_per[:maxhp]
    set = enemy.growth_set[:maxhp]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:maxhp]))
    @base_stats[:maxhp] = result
    return @base_stats[:maxhp]
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: base_maxmp
  #--------------------------------------------------------------------------
  def base_maxmp
    @base_stats = {} if @base_stats == nil
    return @base_stats[:maxmp] if @base_stats[:maxmp] != nil
    @boost_maxmp = 0 if @boost_maxmp == nil
    base = enemy.maxmp + @boost_maxmp
    per = enemy.growth_per[:maxmp]
    set = enemy.growth_set[:maxmp]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:maxmp]))
    @base_stats[:maxmp] = result
    return @base_stats[:maxmp]
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: base_atk
  #--------------------------------------------------------------------------
  def base_atk
    @base_stats = {} if @base_stats == nil
    return @base_stats[:atk] if @base_stats[:atk] != nil
    @boost_atk = 0 if @boost_atk == nil
    base = enemy.atk + @boost_atk
    base = enemy.atk
    per = enemy.growth_per[:atk]
    set = enemy.growth_set[:atk]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:atk]))
    @base_stats[:atk] = result
    return @base_stats[:atk]
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: base_def
  #--------------------------------------------------------------------------
  def base_def
    @base_stats = {} if @base_stats == nil
    return @base_stats[:def] if @base_stats[:def] != nil
    @boost_def = 0 if @boost_def == nil
    base = enemy.def + @boost_def
    per = enemy.growth_per[:def]
    set = enemy.growth_set[:def]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:def]))
    @base_stats[:def] = result
    return @base_stats[:def]
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: base_spi
  #--------------------------------------------------------------------------
  def base_spi
    @base_stats = {} if @base_stats == nil
    return @base_stats[:spi] if @base_stats[:spi] != nil
    @boost_spi = 0 if @boost_spi == nil
    base = enemy.spi + @boost_spi
    per = enemy.growth_per[:spi]
    set = enemy.growth_set[:spi]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:spi]))
    @base_stats[:spi] = result
    return @base_stats[:spi]
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: base_agi
  #--------------------------------------------------------------------------
  def base_agi
    @base_stats = {} if @base_stats == nil
    return @base_stats[:agi] if @base_stats[:agi] != nil
    @boost_agi = 0 if @boost_agi == nil
    base = enemy.agi + @boost_agi
    per = enemy.growth_per[:agi]
    set = enemy.growth_set[:agi]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:agi]))
    @base_stats[:agi] = result
    return @base_stats[:agi]
  end
  
  #--------------------------------------------------------------------------
  # alias method: exp
  #--------------------------------------------------------------------------
  alias exp_enemy_el exp unless $@
  def exp
    base = exp_enemy_el
    per = enemy.growth_per[:exp]
    set = enemy.growth_set[:exp]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:exp]))
    return result
  end
  
  #--------------------------------------------------------------------------
  # alias method: gold
  #--------------------------------------------------------------------------
  alias gold_enemy_el gold unless $@
  def gold
    base = gold_enemy_el
    per = enemy.growth_per[:gold]
    set = enemy.growth_set[:gold]
    result = Integer(eval(YEM::ENEMY_LEVEL::BASE_FORMULAS[:gold]))
    return result
  end
  
  #--------------------------------------------------------------------------
  # new method: states
  #--------------------------------------------------------------------------
  def states
    result = super
    result += level_states
    result.sort! { |state_a,state_b|
      if state_a.priority != state_b.priority
        state_b.priority <=> state_a.priority
      else
        state_a.id <=> state_b.id
      end }
    return result.uniq
  end
  
  #--------------------------------------------------------------------------
  # new method: level_states
  #--------------------------------------------------------------------------
  def level_states
    result = []
    for key in enemy.level_states
      level_requirement = key[0]
      level_state_ids = key[1]
      next unless level >= level_requirement
      for state_id in level_state_ids
        state = $data_states[state_id]
        next if state == nil
        result.push(state) unless result.include?(state)
      end
    end
    return result
  end
  
  #--------------------------------------------------------------------------
  # new method: super_guard
  #--------------------------------------------------------------------------
  def super_guard
    if enemy.level_traits.include?(:super_guard)
      return true if level >= enemy.level_traits[:super_guard]
    end
    return super
  end
  
  #--------------------------------------------------------------------------
  # new method: fast_attack
  #--------------------------------------------------------------------------
  def fast_attack
    if enemy.level_traits.include?(:fast_attack)
      return true if level >= enemy.level_traits[:fast_attack]
    end
    return super
  end
  
  #--------------------------------------------------------------------------
  # new method: dual_attack
  #--------------------------------------------------------------------------
  def dual_attack
    if enemy.level_traits.include?(:dual_attack)
      return true if level >= enemy.level_traits[:dual_attack]
    end
    return super
  end
  
  #--------------------------------------------------------------------------
  # new method: prevent_critical
  #--------------------------------------------------------------------------
  def prevent_critical
    if enemy.level_traits.include?(:prevent_critical)
      return true if level >= enemy.level_traits[:prevent_critical]
    end
    return super
  end
  
  #--------------------------------------------------------------------------
  # new method: half_mp_cost
  #--------------------------------------------------------------------------
  def half_mp_cost
    if enemy.level_traits.include?(:half_mp_cost)
      return true if level >= enemy.level_traits[:half_mp_cost]
    end
    return super
  end
  
  #--------------------------------------------------------------------------
  # alias method: conditions_met?
  #--------------------------------------------------------------------------
  unless $imported["AggroAI"]
  alias conditions_met_el conditions_met? unless $@
  def conditions_met?(action)
    case action.condition_type == 5
    when 5 # Change functionality to match level instead.
      if (self.level - 1) < action.condition_param1
        return false
      else
        return true
      end
    else
      return conditions_met_el(action)
    end
  end
  end # $imported["AggroAI"]
  
end # Game_Enemy

#===============================================================================
# 
# END OF FILE
# 
#===============================================================================