#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Full Reflection System by Blizzard
# Version: 3.01b
# Type: Game Experience Improvement
# Date: 5.9.2006
# Date v1.4: 16.1.2007
# Date v2.0b: 12.3.2007
# Date v2.1b: 13.11.2007
# Date v3.0b: 13.7.2008
# Date v3.01b: 5.12.2008
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#   
#  This work is protected by the following license:
# #----------------------------------------------------------------------------
# #  
# #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# #  
# #  You are free:
# #  
# #  to Share - to copy, distribute and transmit the work
# #  to Remix - to adapt the work
# #  
# #  Under the following conditions:
# #  
# #  Attribution. You must attribute the work in the manner specified by the
# #  author or licensor (but not in any way that suggests that they endorse you
# #  or your use of the work).
# #  
# #  Noncommercial. You may not use this work for commercial purposes.
# #  
# #  Share alike. If you alter, transform, or build upon this work, you may
# #  distribute the resulting work only under the same or similar license to
# #  this one.
# #  
# #  - For any reuse or distribution, you must make clear to others the license
# #    terms of this work. The best way to do this is with a link to this web
# #    page.
# #  
# #  - Any of the above conditions can be waived if you get permission from the
# #    copyright holder.
# #  
# #  - Nothing in this license impairs or restricts the author's moral rights.
# #  
# #----------------------------------------------------------------------------
# 
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# 
# new in v1.4:
#   - overworked code and fixed all the glitches
#   - the power comes back X times stronger if it is reflected from X battlers
#     (i.e. like in the Final Fantasy series)
#   - spells now get reflected to anybody from the enemy party, not only the
#     user (makes it possible to split damage from the FF feature mentioned
#     above)
#   - added a fix so it works with HP/SP Absorb
# 
# new in v2.0b:
#   - completely overworked and fixed
# 
# new in v2.1b:
#   - overworked and independent from Tons of Add-ons
# 
# new in v3.0b:
#   - fixed a little bug based on HP/SP Absorb Skills
#   - better coding
#   - commented code
#   - now compatible with Blizz-ABS 1.99 or higher
# 
# new in v3.01b:
#   - now compatible with Blizz-ABS 2.11 or higher
# 
# 
# Compatibility:
# 
#   97% compatible with SDK v1.x. 80% compatible with SDK v2.x. You might
#   experience problems with exotic CBS-es.
# 
# 
# Configuration:
# 
#   Make a status effect and call it "Reflect". Remember the ID number. Now
#   make an animation that should be displayed when reflecting magic.
# 
#     REFLECT_ID        - the ID of the reflect status
#     REFLECT_ANIMATION - the ID of animation displayed when magic is being
#                         reflecting
#     BREAK_REFLECT     - IDs of skills that go through Reflection no matter
#                         what
#     MISS_DAMAGE       - what is displayed in your game if somebody gets
#                         missed (usually 'Miss')
# 
# Notes:
# 
#   A magical skill is considered a skill that has a either INT-F greater than
#   zero or MDEF-F greater than zero. Please note that skills that can disable
#   the reflection status break through the reflection automatically. Also, it
#   is better if you don't use sounds and screen/target flashing in the
#   animation for the reflecting effect.
#   
#   
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

$full_reflection_system = 3.01

#==============================================================================
# module BlizzCFG
#==============================================================================

module BlizzCFG

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START COnfiguration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

  REFLECT_ID = 18
  REFLECT_ANIMATION = 61
  BREAK_REFLECT = []
  MISS_DAMAGE = 'Miss'

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END COnfiguration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

  #----------------------------------------------------------------------------
  # reflection_effect
  #  battler - battler using the skill
  #  targets - targeted battlers
  #  skill   - the skill being used
  #  Executes complete replacement processing of targeted battlers when
  #  reflecting.
  #----------------------------------------------------------------------------
  def self.reflection_effect(battler, targets, skill)
    # old targets
    old_targets = []
    # for each target
    targets.each_index {|i|
        # if skill exists, using skill and target reflects
        if skill != nil && battler.current_action.kind == 1 &&
            targets[i].test_reflection(skill)
          # swap the targtet with a new one
          new_target = self.swap_target(battler, targets[i], skill)
          # if the new target is different from the one before
          if targets[i] != new_target
            # remember old target
            old_targets.push(targets[i])
            # set new target
            targets[i] = new_target
          end
        end}
    # remove nils
    targets.compact!
    # for each target
    targets.each {|target|
        # get damage
        dam = (target.damage.is_a?(Numeric) ? target.damage : 0)
        # execute skill and override reflection
        target.skill_effect(battler, skill, true)
        # add damage if already damaged
        target.damage += dam if target.damage.is_a?(Numeric)
        # set hit animation if not missed
        target.animation_hit = (target.damage != MISS_DAMAGE)}
    # return old targets
    return old_targets
  end
  #----------------------------------------------------------------------------
  # swap_target
  #  b1    - battler using skill
  #  b2    - battler being attacked
  #  skill - the skill being used
  #  Swaps the targeted battler with another one so a reflection effect is
  #  achieved.
  #----------------------------------------------------------------------------
  def self.swap_target(b1, b2, skill)
    # if enemy is targeted
    if b2.is_a?(Game_Enemy)
      # get valid actor targets
      bs = $game_party.actors.find_all {|actor| actor.exist?}
    # if actor is targeted
    elsif b2.is_a?(Game_Actor)
      # get valid enemy targets
      bs = $game_troop.enemies.find_all {|enemy| enemy.exist?}
    else
      # target doesn't change
      bs = [b2]
    end
    # return a random target of all possible targets
    return bs[rand(bs.size)]
  end
  #----------------------------------------------------------------------------
  # reflection_effect_blizzabs
  #  battler - battler using the skill
  #  targets - targeted battlers
  #  other   - alternative targets
  #  skill   - the skill being used
  #  Replaces all battlers that have reflection with other battlers.
  #----------------------------------------------------------------------------
  def self.reflection_effect_blizzabs(battler, targets, other, skill)
    # old targets
    old_targets = []
    # for each target
    targets.each_index {|i|
        # if skill exists, using skill and target reflects
        if skill != nil && targets[i].battler.test_reflection(skill)
          # swap the target with a new one
          new_target = self.swap_target_blizzabs(battler, targets[i], other, skill)
          # if the new target is different from the one before
          if targets[i] != new_target
            # remember old target
            old_targets.push(targets[i])
            # set new target
            targets[i] = new_target
          end
        end}
    # if animations are being used
    if BlizzABS::Config::ANIMATIONS
      # set animation to reflecting for all old targets
      old_targets.each {|target| target.animation_id = REFLECT_ANIMATION}
    end
  end
  #----------------------------------------------------------------------------
  # swap_target_blizzabs
  #  b1    - battler using skill
  #  b2    - battler being attacked
  #  other - alternative targets
  #  skill - the skill being used
  #  Swaps the targeted map battler with another one so a reflection effect is
  #  achieved.
  #----------------------------------------------------------------------------
  def self.swap_target_blizzabs(b1, b2, other, skill)
    # find all targets that are negative aligned from the targeted battler
    bs = other.find_all {|b| b2.ai.negative.include?(b.ai.basic)}
    # set original target if no other targets exist
    bs = [b2] if bs.size == 0
    # return a random target of all possible targets
    return bs[rand(bs.size)]
  end
  
end

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

class Game_Battler
  
  #----------------------------------------------------------------------------
  # override skill_effect
  #----------------------------------------------------------------------------
  alias skill_effect_reflect_later skill_effect
  def skill_effect(user, skill, override_reflect = !$scene.is_a?(Scene_Battle))
    # if in Blizz-ABS mode on the map
    if $BlizzABS && BlizzABS::VERSION >= 1.99 && $scene.is_a?(Scene_Map)
      # set reflect inactive
      override_reflect = true
    end
    # if reflect is not active
    if override_reflect || !test_reflection(skill)
      # execute skill
      return skill_effect_reflect_later(user, skill)
    end
    # not skill execution
    return false
  end
  #----------------------------------------------------------------------------
  # test_reflection
  #  skill - the skill to be check
  #  Checks whether a skill should be reflected.
  #----------------------------------------------------------------------------
  def test_reflection(skill)
    return ((skill.int_f > 0 || skill.mdef_f > 0) &&
        @states.include?(BlizzCFG::REFLECT_ID) &&
        !BlizzCFG::BREAK_REFLECT.include?(skill.id) &&
        !skill.minus_state_set.include?(BlizzCFG::REFLECT_ID))
  end
  
end

#==============================================================================
# Scene_Battle
#==============================================================================

class Scene_Battle
  
  #----------------------------------------------------------------------------
  # override main
  #----------------------------------------------------------------------------
  alias main_reflect_later main
  def main
    # initialize array of old targets
    @old_targets = []
    # call original method
    main_reflect_later
  end
  #----------------------------------------------------------------------------
  # override set_target_battlers
  #----------------------------------------------------------------------------
  alias set_target_battlers_reflect_later set_target_battlers
  def set_target_battlers(scope, battler = nil, override = false)
    # if skill can't break through reflection this time
    if !BlizzCFG::BREAK_REFLECT.include?(@skill.id) && !override &&
        @active_battler.current_action.kind == 1
      # no targets
      return []
    end
    # if RTAB is not installed
    if battler == nil
      # call original method
      return set_target_battlers_reflect_later(scope)
    else
      # call original method with RTAB compatibility
      return set_target_battlers_reflect_later(scope, battler)
    end
  end
  #----------------------------------------------------------------------------
  # override make_skill_action_result
  #----------------------------------------------------------------------------
  alias make_skill_action_result_reflect_later make_skill_action_result
  def make_skill_action_result(battler = nil, plus_id = nil)
    # if RTAB is not installed
    if battler == nil
      # call original method
      make_skill_action_result_reflect_later
      # set battler and targets
      tmp, targets = @active_battler, @target_battlers
    # additional compatibility
    elsif plus_id == nil
      # call original method with RTAB compatibility
      make_skill_action_result_reflect_later(battler)
      # set targets
      targets = battler.target
    else
      # call original method with higher RTAB compatibility
      make_skill_action_result_reflect_later(battler, plus_id)
      # set targets
      targets = battler.target
    end
    # if not breaking reflection skill
    unless BlizzCFG::BREAK_REFLECT.include?(@skill.id)
      # set targets allowing reflection
      set_target_battlers(@skill.scope, battler, true)
      # set battler if doesn't exist
      battler = tmp if battler == nil && tmp != nil
      # execute reflection effect and get old targets
      @old_targets = BlizzCFG.reflection_effect(battler, targets, @skill)
    end
  end
  #----------------------------------------------------------------------------
  # override make_skill_action_result
  #----------------------------------------------------------------------------
  alias update_phase4_step4_reflect_later update_phase4_step4
  def update_phase4_step4(battler = nil)
    # change animation to reflecting for all old targets
    @old_targets.each {|target|
        target.animation_id = BlizzCFG::REFLECT_ANIMATION}
    # empty old targets
    @old_targets = []
    # if RTAB not installed
    if battler == nil
      # call original method
      update_phase4_step4_reflect_later
    else
      # call original method with RTAB compatibility
      update_phase4_step4_reflect_later(battler)
    end
  end
  
end
