#===============================================================================
# 
# Yanfly Engine Melody - Controlled Encounter Rates
# Last Date Updated: 2010.06.30
# Level: Normal
# 
# This script balances out the encounter rates and fixes them in such a way
# where an encounter rate of 30 won't suddenly net 4 steps for one battle and
# then 60 steps for the following. In addition to balancing out the encounter
# rates, repel and lure capabilities are added to allow for control regarding
# encounter rates. And finally, skin functionality is added for encounters.
# 
#===============================================================================
# Updates
# -----------------------------------------------------------------------------
# o 2010.06.30 - Started Script and Finished.
#===============================================================================
# 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.
# 
# There are four variables to bind in this script. Adjust them properly in
# Section I of the script.
# 
#===============================================================================

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

module YEM
  module ENCOUNTER
    
    #===========================================================================
    # Section I. Basic Settings
    # --------------------------------------------------------------------------
    # The following below will adjust the variables used for this script and
    # some of the hard-coded rules applied for encounter rates. The variables
    # used in this script will adjust Repel and Lure variables and their own
    # respective modifiers.
    #===========================================================================
    
    # Anything that isn't an overworld tile is considered a bush tile. And for
    # bush tiles, the default reduction is actually 2, making encounters come
    # out even more often than they appear in the editor. This constant here
    # will set the reduction rate to 1, but should you decide to make it remain
    # as 2, just simply change it.
    BUSH_REDUCTION = 1   # Countdown reduction on a bush tile.
    NORM_REDUCTION = 1   # Countdown reduction on a normal tile.
    
    # This variable updates the amount of steps remaining before a battle. This
    # variable is used for eventing purposes only.
    STEPS_REMAINING_VARIABLE = 61
    
    # This is the amount of steps free of battle the player receives if the
    # variable's value is above 1. A common event can also run after this value
    # hits 0. To make no common event run, set the common event to 0.
    REPEL_STEPS_VARIABLE = 62
    REPEL_COMMON_EVENT   = 13   # Set this value to 0 if you want no event.
    
    # This is the amount of steps with a higher countdown reduction rate until
    # battle. For a rate of 4, the encounter rate will drop by 4 each step. The
    # lure common event will run when the value reaches 0.
    LURE_STEPS_VARIABLE  = 63
    LURE_RATE_VARIABLE   = 64
    LURE_COMMON_EVENT    = 14   # Set this value to 0 if you want no event.
    
    #===========================================================================
    # Section II. Encounter Countdown Settings
    # --------------------------------------------------------------------------
    # This section adjusts the way the encounter countdown is created. By
    # default, the encounter rate is randomized twice and the sum of those
    # random numbers becomes the encounter countdown. This can become a problem
    # and make encounters either too close or too far from each other. Adjust
    # the settings below to alter the rate at which encounters are adjusted.
    #===========================================================================
    
    # This is the number of times the encounter rate is rolled when creating a
    # new encounter rate. The value is then averaged.
    ENCOUNTER_ROLLS = 4
    
    # No matter what, this is how many steps the player is allowed free of
    # battle upon finishing the previous battle.
    MINIMUM_FREE_STEPS = 10
    
    #===========================================================================
    # Section III. Visual Encounter Indicator
    # --------------------------------------------------------------------------
    # The visual encounter indicator will appear on the screen to show players
    # how close they are to a random battle. By default, when the player is
    # far from entering a battle, the indicator will be a blue colour. When the
    # player is close to entering a battle, the indicator will be a red colour.
    #===========================================================================
    
    # If this constant is set to true, then the script will show the indicator
    # on the screen. If it's set to false, then the indicator will not appear
    # and this section can be ignored.
    USE_INDICATOR = true
    
    # This is the indicator image used that appears behind the changing (main)
    # indicator and appears static (does not change colours). Place this image
    # inside of the Graphics\System folder.
    INDICATOR_BACK_IMAGE = "Encounter0"
    
    # This is the main indicator image used that will change colours depending
    # on the amount of steps remaining. Place this image inside of the
    # Graphics\System folder.
    INDICATOR_MAIN_IMAGE = "Encounter1"
    
    # These two constants adjust the x and y position of the indicators shown
    # on the screen. The coordinates used apply to the upper left corner of the
    # indicator itself.
    INDICATOR_X_POSITION = -12
    INDICATOR_Y_POSITION = Graphics.height - 36
    
    # This hash adjusts the colours used for the indicator when it approaches
    # a percentage of how many steps are left.
    INDICATOR_COLOURS ={
      100 => [  0,   0, 200],
       90 => [ 50,  50, 200],
       80 => [100, 200, 250],
       70 => [150, 250, 150],
       60 => [200, 200, 100],
       50 => [250, 175, 100],
       40 => [250, 150,  75],
       30 => [250, 100,  50],
       20 => [250,   0,   0],
       10 => [250,   0,   0],
    } # Do not remove this.
    
  end # ENCOUNTER
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.
#===============================================================================

#===============================================================================
# Spriteset_Map
#===============================================================================

class Spriteset_Map
  
  #--------------------------------------------------------------------------
  # alias method: initialize
  #--------------------------------------------------------------------------
  alias initialize_cer initialize unless $@
  def initialize
    initialize_cer
    create_encounter_indicator
  end
  
  #--------------------------------------------------------------------------
  # new method: create_encounter_indicator
  #--------------------------------------------------------------------------
  def create_encounter_indicator
    return unless YEM::ENCOUNTER::USE_INDICATOR
    return unless $scene.is_a?(Scene_Map)
    @indicator_back_sprite = Sprite_Base.new(@viewport3)
    bitmap = Cache.system(YEM::ENCOUNTER::INDICATOR_BACK_IMAGE)
    @indicator_back_sprite.bitmap = bitmap
    @indicator_back_sprite.x = YEM::ENCOUNTER::INDICATOR_X_POSITION
    @indicator_back_sprite.y = YEM::ENCOUNTER::INDICATOR_Y_POSITION
    @indicator_main_sprite = Sprite_Base.new(@viewport3)
    bitmap = Cache.system(YEM::ENCOUNTER::INDICATOR_MAIN_IMAGE)
    @indicator_main_sprite.bitmap = bitmap
    @indicator_main_sprite.x = YEM::ENCOUNTER::INDICATOR_X_POSITION
    @indicator_main_sprite.y = YEM::ENCOUNTER::INDICATOR_Y_POSITION
    update_encounter_indicator(true)
  end
  
  #--------------------------------------------------------------------------
  # alias method: dispose
  #--------------------------------------------------------------------------
  alias dispose_cer dispose unless $@
  def dispose
    dispose_cer
    dispose_encounter_indicator
  end
  
  #--------------------------------------------------------------------------
  # new method: dispose_encounter_indicator
  #--------------------------------------------------------------------------
  def dispose_encounter_indicator
    @indicator_back_sprite.dispose unless @indicator_back_sprite == nil
    @indicator_main_sprite.dispose unless @indicator_main_sprite == nil
  end
  
  #--------------------------------------------------------------------------
  # alias method: update
  #--------------------------------------------------------------------------
  alias update_cer update unless $@
  def update
    update_cer
    update_encounter_indicator
  end
  
  #--------------------------------------------------------------------------
  # new method: update_encounter_indicator
  #--------------------------------------------------------------------------
  def update_encounter_indicator(instant = false)
    update_back_indicator
    update_main_indicator(instant)
  end
  
  #--------------------------------------------------------------------------
  # new method: update_back_indicator
  #--------------------------------------------------------------------------
  def update_back_indicator
    return if @indicator_back_sprite == nil
    adjust_indicator_opacity(@indicator_back_sprite)
    @indicator_back_sprite.update
  end
  
  #--------------------------------------------------------------------------
  # new method: update_main_indicator
  #--------------------------------------------------------------------------
  def update_main_indicator(instant = false)
    return if @indicator_main_sprite == nil
    change_main_indicator_colour
    update_indicator_colour(instant)
    adjust_indicator_opacity(@indicator_main_sprite)
    @indicator_main_sprite.update
  end
  
  #--------------------------------------------------------------------------
  # new method: change_main_indicator_colour
  #--------------------------------------------------------------------------
  def change_main_indicator_colour
    return if @indicator_main_sprite == nil
    return if $game_map.encounter_step <= 0
    return if @encounter_count == $game_player.encounter_count_calc
    @encounter_count = $game_player.encounter_count_calc
    count = $game_player.encounter_count - 1
    count += $game_variables[YEM::ENCOUNTER::REPEL_STEPS_VARIABLE]
    if $game_variables[YEM::ENCOUNTER::LURE_STEPS_VARIABLE] > 0
      count -= [$game_variables[YEM::ENCOUNTER::LURE_RATE_VARIABLE], 1].max
    end
    percent = count * 100 / $game_map.encounter_step
    @indicator_colour = YEM::ENCOUNTER::INDICATOR_COLOURS[100]
    for i in [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]
      next if i == nil
      break if percent > i
      @indicator_colour = YEM::ENCOUNTER::INDICATOR_COLOURS[i]
    end
  end
  
  #--------------------------------------------------------------------------
  # new method: update_indicator_colour
  #--------------------------------------------------------------------------
  def update_indicator_colour(instant = false)
    return if @indicator_colour == nil
    if instant
      a1 = @indicator_colour[0]
      a2 = @indicator_colour[1]
      a3 = @indicator_colour[2]
    else
      #---
      s = 4
      if @indicator_main_sprite.color.red > @indicator_colour[0]
        a1 = [@indicator_main_sprite.color.red-s, @indicator_colour[0]].max
      else
        a1 = [@indicator_main_sprite.color.red+s, @indicator_colour[0]].min
      end
      #---
      if @indicator_main_sprite.color.green > @indicator_colour[1]
        a2 = [@indicator_main_sprite.color.green-s, @indicator_colour[1]].max
      else
        a2 = [@indicator_main_sprite.color.green+s, @indicator_colour[1]].min
      end
      #---
      if @indicator_main_sprite.color.blue > @indicator_colour[2]
        a3 = [@indicator_main_sprite.color.blue-s, @indicator_colour[2]].max
      else
        a3 = [@indicator_main_sprite.color.blue+s, @indicator_colour[2]].min
      end
      #---
    end
    @indicator_main_sprite.color.set(a1, a2, a3, 128)
  end
  
  #--------------------------------------------------------------------------
  # new method: adjust_indicator_opacity
  #--------------------------------------------------------------------------
  def adjust_indicator_opacity(sprite)
    return if sprite == nil
    if $game_map.encounter_step <= 0
      opacity_rate = -8
    elsif $game_map.encounter_list == [] or $game_message.visible
      opacity_rate = -255
    else
      opacity_rate = 8
    end
    sprite.opacity += opacity_rate
  end
  
end # Spriteset_Map

#===============================================================================
# Game_Player
#===============================================================================

class Game_Player < Game_Character
  
  #--------------------------------------------------------------------------
  # new method: encounter_count_calc
  #--------------------------------------------------------------------------
  alias encounter_count_cer encounter_count unless $@
  def encounter_count_calc
    n = encounter_count_cer
    n += $game_variables[YEM::ENCOUNTER::REPEL_STEPS_VARIABLE]
    if $game_variables[YEM::ENCOUNTER::LURE_STEPS_VARIABLE] > 0
      n -= [$game_variables[YEM::ENCOUNTER::LURE_RATE_VARIABLE], 1].max
    end
    return n
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: make_encounter_count
  #--------------------------------------------------------------------------
  def make_encounter_count
    return if $game_map.map_id <= 0
    n = $game_map.encounter_step
    sum = 0
    YEM::ENCOUNTER::ENCOUNTER_ROLLS.times do sum += rand(n) end
    @encounter_count = sum/YEM::ENCOUNTER::ENCOUNTER_ROLLS
    @encounter_count += YEM::ENCOUNTER::MINIMUM_FREE_STEPS
    @encounter_count = [@encounter_count, 1].max
  end

  #--------------------------------------------------------------------------
  # overwrite method: update_encounter
  #--------------------------------------------------------------------------
  def update_encounter
    if $game_variables[YEM::ENCOUNTER::REPEL_STEPS_VARIABLE] > 0
      $game_variables[YEM::ENCOUNTER::REPEL_STEPS_VARIABLE] -= 1
      return unless $game_variables[YEM::ENCOUNTER::REPEL_STEPS_VARIABLE] <= 0
      $game_temp.common_event_id = YEM::ENCOUNTER::REPEL_COMMON_EVENT
      return
    end
    #---
    return if $TEST and Input.press?(Input::CTRL)
    return if in_vehicle?
    #---
    if $game_map.bush?(@x, @y)
      @encounter_count -= YEM::ENCOUNTER::BUSH_REDUCTION
    else
      @encounter_count -= YEM::ENCOUNTER::NORM_REDUCTION
    end
    #---
    if $game_variables[YEM::ENCOUNTER::LURE_STEPS_VARIABLE] > 0
      $game_variables[YEM::ENCOUNTER::LURE_STEPS_VARIABLE] -= 1
      rate = [$game_variables[YEM::ENCOUNTER::LURE_RATE_VARIABLE], 1].max
      @encounter_count -= rate
      if $game_variables[YEM::ENCOUNTER::LURE_STEPS_VARIABLE] <= 0
        $game_temp.common_event_id = YEM::ENCOUNTER::LURE_COMMON_EVENT
      end
    end
    #---
    $game_variables[YEM::ENCOUNTER::STEPS_REMAINING_VARIABLE] = @encounter_count
  end
  
end # Game_Player

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