#===============================================================================
#                       Substance Script
#                       Ver: 1.0
#                       Author: Day Ja Voo Games (Hunter Heidenreich)
#                       Date: July 18, 2013
#-------------------------------------------------------------------------------
#   Description: A script that allows you to implement the effects of toxins 
#                such as poison in the air or even drugs and alcohol into your
#                game.  This can be done through tiles or through items that you
#                may implement.  So far, these effects only work on the main
#                character, editing a hidden value that can be accessed through
#                the menu.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
#   Version History:
#   
#     Ver 1.0
#       - Created Script
#       - Added Item and Tile Customization
#       - Added Intoxication Effects
#       - Add SFX
#       - Created Scene to View Values
#------------------------------------------------------------------------------
#   Planned for Future Updates
#       v1.1
#       - Customizable Message Alert System
#       - Death Cries Upon Death
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#   Instructions - Modify the Editable Region :)
#===============================================================================


#==================================Editable Region==============================
module DayJaVooGames
  module Substance_FX
    #==========================================================================
    # Basic Toxin Information
    MaximumAmountOfToxin = 1000 #The maximum amount of toxin a player can take
    SoberPerStep         = 1    #The amount of toxin lost per step
    PointsPerAffliction  = 100   #Amount of poision absorbed per affliction
    AfflictionSFXName    = "Attack1" #Sound Effect played on Affliction
    AfflictionColor      = Color.new(255, 0, 0) #Color the screen flashes
    AfflictionBuffer     = 30   #Buffer between afflictions
    DieOnOD              = true #Does player die when they hit max
    MenuCommandText      = "Substance Levels" #Menu option for view substance levels
    SicknessEffectName   = "Dry Cough-SoundBible.com-1957692509" # For Example: a Cough
    #==========================================================================
    # Terrain Tag Info
    TerrainTagTrigger = true  #Whether you want terrain to affect toxin
    TerrainIDTrigger  = 1     #What tag you give the toxic tile
    #==========================================================================
    # Scene Window Information
    WarningWindowText1  = "No toxins in the body.  \nFeeling great!"
    WarningWindowText2  = "Feeling a litty woozy... \nMaybe I should stop what I'm doing."
    WarningWindowText3  = "Now... now... I don't... \nI can't see straight..."
    WarningWindowText4  = "I really need to rest.  \nI don't think much more of this will do good."
    WarningWindowText5  = "I can't take much more. \nI think I might die..."
  end
end

#==================================End of Editable==============================


#==============================================================================
# ** Game_Actor
#------------------------------------------------------------------------------
#  This class handles actors. It is used within the Game_Actors class
# ($game_actors) and is also referenced from the Game_Party class ($game_party).
#==============================================================================
class Game_Actor < Game_Battler
  include DayJaVooGames::Substance_FX
  #--------------------------------------------------------------------------
  # * Public instance variables
  #--------------------------------------------------------------------------
  attr_accessor :toxic_level
  attr_reader   :max_toxins
  #--------------------------------------------------------------------------
  # * Intits everything
  #--------------------------------------------------------------------------
  alias dayjavoo_gameplayer_initialize_substancefx initialize
  def initialize(actor_id)
    dayjavoo_gameplayer_initialize_substancefx(actor_id)
    @toxic_level = toxic_level
    @toxic_level = 0 if !@toxic_level 
    @max_toxins = MaximumAmountOfToxin
  end
end

#==============================================================================
# ** Substance_FX
#------------------------------------------------------------------------------
#  This class triggers everything to do with substances.
#==============================================================================
class Substance_FX 
  include DayJaVooGames::Substance_FX
  #--------------------------------------------------------------------------
  # * Intits everything
  #--------------------------------------------------------------------------
  def initialize()
    @se_buffer = 0
    @se_limit = rand(5) + 1
  end
  #--------------------------------------------------------------------------
  # * Basic update that applies to the map
  #--------------------------------------------------------------------------
  def update()
    if TerrainTagTrigger
      @current_tag = get_terrain_tag()
      if @current_tag == TerrainIDTrigger
        increase_toxic_level(true)
      else
        decrease_toxic_level()
      end
    else
      decrease_toxic_level()
    end
    if Graphics.brightness < 150 && @se_buffer >= @se_limit
      @se_buffer = 0
      @se_limit = rand(5) + 1
      RPG::SE.new(SicknessEffectName, 100, 100).play()
    end
    @se_buffer += 1
  end
  #--------------------------------------------------------------------------
  # * (Planned) Message System Update
  #--------------------------------------------------------------------------
  def update_message()
    if Graphics.brightness < 13
      you_die()
      return true
    elsif Graphics.brightness < 53
      
      return true
    elsif Graphics.brightness < 128
      
      return true
    end
    return false
  end
  #--------------------------------------------------------------------------
  # * Increases toxic levels in system
  #--------------------------------------------------------------------------
  def increase_toxic_level(map, toxic = PointsPerAffliction)
    $game_party.battle_members.each do |actor|
      actor.toxic_level += toxic
    end
    if(map)
      RPG::SE.new(AfflictionSFXName, 100, 100).play()
      $game_map.screen.start_flash(AfflictionColor, 4)
    end
    
  end
  #--------------------------------------------------------------------------
  # * Decreases players toxic level
  #--------------------------------------------------------------------------
  def decrease_toxic_level(sober = SoberPerStep) 
    if $game_party.leader.toxic_level > 0
      $game_party.battle_members.each do |actor|
        actor.toxic_level -= sober if(actor.hp > 0)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * (Debug)Prints players toxic levels
  #--------------------------------------------------------------------------
  def print_toxic_levels()
    msgbox_p($game_player.toxic_level)
  end
  #--------------------------------------------------------------------------
  # * Reads the terrain tag
  #--------------------------------------------------------------------------
  def get_terrain_tag
    return $game_map.terrain_tag($game_player.x, $game_player.y)
  end
  #--------------------------------------------------------------------------
  # * Observes the brightness and updates
  #--------------------------------------------------------------------------
  def update_brightness()
    @bringtness = (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i
    Graphics.brightness = @bringtness
    if Graphics.brightness < 200
      $game_map.screen.start_shake(2, 2, 100) 
    elsif Graphics.brightness < 150
      $game_map.screen.start_shake(8, 8, 100) 
    elsif Graphics.brightness < 100
      $game_map.screen.start_shake(32, 20, 100) 
    elsif Graphics.brightness < 50
      $game_map.screen.start_shake(50, 40, 100) 
    end
    $game_party.members.each do |actor|
      actor.toxic_level = actor.max_toxins if actor.toxic_level > actor.max_toxins
      actor.hp = 0 if actor.toxic_level == actor.max_toxins
    end
  end
  #--------------------------------------------------------------------------
  # * Function called upon death
  #--------------------------------------------------------------------------
  def you_die()
    if DieOnOD
      $game_party.leader.hp = 0
      i = 0
      $game_party.battle_members.each do |actor|
        if $game_party.leader.hp == 0
          if actor.hp > 0
            $game_party.swap_order($game_party.leader.index, actor.index)
          end
        end
      end
    else
      $game_party.leader.hp = 1
    end
  end
end



#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
#  This class performs the map screen processing.
#==============================================================================

class Scene_Map < Scene_Base
  include DayJaVooGames::Substance_FX
  #--------------------------------------------------------------------------
  # * Inits the scene map
  #--------------------------------------------------------------------------
  alias dayjavoo_scenemap_initialize_substancefx initialize
  def initialize
    dayjavoo_scenemap_initialize_substancefx()
    @substance_check = Substance_FX.new()
    @substance_buff = 0
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  alias dayjavoo_scenemap_update_substancefx update
  def update
    dayjavoo_scenemap_update_substancefx()
    if(Input.trigger?(:DOWN) || Input.trigger?(:RIGHT) || Input.trigger?(:UP) || Input.trigger?(:LEFT))
      @substance_buff += 1
      if @substance_buff >= AfflictionBuffer
        @substance_check.update()
        @substance_buff = 0
      end
    elsif(Input.press?(:DOWN) || Input.press?(:RIGHT) || Input.press?(:UP) || Input.press?(:LEFT))
      @substance_buff += 1
      if @substance_buff >= AfflictionBuffer
        @substance_check.update()
        @substance_buff = 0
      end
    end
    @substance_check.update_message()
    @substance_check.update_brightness()
  end
end


#==============================================================================
# ** Scene_ItemBase
#------------------------------------------------------------------------------
#  This class performs common processing for the item screen and skill screen.
#==============================================================================

class Scene_ItemBase < Scene_MenuBase
  #--------------------------------------------------------------------------
  # * Starts scene item base processing
  #--------------------------------------------------------------------------
  alias dayjavoo_sceneitembase_start_substancefx start
  def start
    dayjavoo_sceneitembase_start_substancefx()
    @substance_drink = Substance_FX.new()
    @substance_drink.update_brightness()
    @exit_scene = false
  end 
  #--------------------------------------------------------------------------
  # * Use Item on Actor
  #--------------------------------------------------------------------------
  def use_item_to_actors
    item_target_actors.each do |target|
      $data_items[item.id].note[/<Substance\s*FX:(\s*\d\d*\d*), (\d*)>/im]
        if $2 && $2 != ""
          if $2.to_i == 1
            if $1 && $1 != ""
              target.toxic_level -= $1.to_i
            end
          else
            if $1 && $1 != ""
              target.toxic_level += $1.to_i
            end
          end
        end
      @substance_drink.update_brightness()
      @exit_scene = @substance_drink.update_message()
      item.repeats.times { target.item_apply(user, item) }
    end
  end
end

#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  This class performs the menu screen processing.
#==============================================================================

class Scene_Menu < Scene_MenuBase
  #--------------------------------------------------------------------
  # * Create Command Window
  #--------------------------------------------------------------------------
  alias dayjavoo_scenemenu_createcommandwindow_substancefx create_command_window
  def create_command_window
    dayjavoo_scenemenu_createcommandwindow_substancefx()
    @command_window.set_handler(:subsctance_fx,    method(:command_substance))
  end
  #--------------------------------------------------------------------------
  # * Starts the scene
  #--------------------------------------------------------------------------
  def command_substance
    SceneManager.call(Scene_Substance)
  end
end

#==============================================================================
# ** Window_MenuCommand
#------------------------------------------------------------------------------
#  This command window appears on the menu screen.
#==============================================================================

class Window_MenuCommand < Window_Command
  #--------------------------------------------------------------------------
  # * Add Exit Game to Command List
  #--------------------------------------------------------------------------
  alias dayjavoo_windowmenucommand_addgameendcommand_substancefx add_game_end_command
  def add_game_end_command
    add_command(DayJaVooGames::Substance_FX::MenuCommandText, :subsctance_fx)
    dayjavoo_windowmenucommand_addgameendcommand_substancefx()
  end
end

#==============================================================================
# ** Scene_Substance
#------------------------------------------------------------------------------
#  Class that holds scene info for the viewing substance levels
#==============================================================================
class Scene_Substance < Scene_Base
    include DayJaVooGames::Substance_FX
  #--------------------------------------------------------------------------
  # * Start Processing
  #--------------------------------------------------------------------------
  def start()
    super()
    help_startup()
    @substance_info = Window_SubstanceInfo.new()
    @substance_info.x = 0
    @substance_info. y = 72
    @substance_info.open
    @substance_info.openness = 255
  end
  #--------------------------------------------------------------------------
  # * Post-Start Processing
  #--------------------------------------------------------------------------
  def post_start
    super()
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super()
    @actor = 0
    @even = 0
    @odd = 0
    @divi = true
    @substance_info.contents.clear
    $game_party.battle_members.each do |actor|
      @axe = @actor%2
      if @actor%2==0
        @divi = true
      else
        @divi = false
      end
      @substance_info.draw_face(actor.face_name, actor.face_index, (Graphics.width / 2) * @axe, (@even * 200), true) if @divi
      @substance_info.draw_face(actor.face_name, actor.face_index, (Graphics.width / 2) * @axe, (@even * 200), true) if !@divi
      @substance_info.draw_actor_name(actor, (Graphics.width / 2) * @axe,  100) if @actor < 2
      @substance_info.draw_actor_name(actor, (Graphics.width / 2) * @axe, (@even * 300)) if @actor >= 2
      @substance_info.draw_gauge((Graphics.width / 2) * @axe + 100, (@even * 300) + 70, 150, (actor.toxic_level.to_f / actor.max_toxins), Color.new(204, 153, 255), Color.new(102, 0, 102))  if @actor < 2
      @substance_info.draw_gauge((Graphics.width / 2) * @axe + 100, (@even * 270), 150, (actor.toxic_level.to_f / actor.max_toxins), Color.new(204, 153, 255), Color.new(102, 0, 102))  if @actor >= 2
      @substance_info.draw_text_substance_window((Graphics.width / 2) * @axe + 100, (@even * 300) + 30, ((((actor.toxic_level.to_f / actor.max_toxins).to_f) * 100).to_i).to_s + "%") if @actor < 2
      @substance_info.draw_text_substance_window((Graphics.width / 2) * @axe + 100, (@even * 270) - 40, ((((actor.toxic_level.to_f / actor.max_toxins).to_f) * 100).to_i).to_s + "%") if @actor >= 2
      @actor += 1
      if @actor%2==0
        @even += 1
      else
        @odd += 1
      end
    end
    @substance_info.contents.fill_rect(0, 165, @substance_info.contents_width, 2, Color.new(255, 255, 255, 48))
    update_help()
    return_scene()          if Input.trigger?(:B)
   end
  #--------------------------------------------------------------------------
  # * Pre-Termination Processing
  #--------------------------------------------------------------------------
  def pre_terminate
    super()
  end
  #--------------------------------------------------------------------------
  # * Termination Processing
  #--------------------------------------------------------------------------
  def terminate
    @substance_info.dispose if !@substance_info.disposed?()
    @help_window.dispose    if !@help_window.disposed?()
    super()
  end
  def help_startup() 
    @help_window = Window_Help.new()
    if  (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 50
      @help_window.set_text(WarningWindowText5)
    elsif (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 100
      @help_window.set_text(WarningWindowText4)
    elsif (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 150
      @help_window.set_text(WarningWindowText3)
    elsif (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 255
      @help_window.set_text(WarningWindowText2)
    else
      @help_window.set_text(WarningWindowText1)
    end
  end
  def update_help()
    if (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 50
      @help_window.set_text(WarningWindowText5)
    elsif (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 100
      @help_window.set_text(WarningWindowText4)
    elsif (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 150
      @help_window.set_text(WarningWindowText3)
    elsif (255 * (1.0 - ($game_party.leader.toxic_level.to_f / $game_party.leader.max_toxins.to_f))).to_i < 255
      @help_window.set_text(WarningWindowText2)
    else
      @help_window.set_text(WarningWindowText1)
    end
  end
end


#==============================================================================
# ** Window_SubstanceInfo
#------------------------------------------------------------------------------
#  The Substance Info Window
#==============================================================================
class Window_SubstanceInfo < Window_Message
  #--------------------------------------------------------------------------
  # * Sets the font of the window
  #--------------------------------------------------------------------------
  def set_font(user_color)
    contents.font.size = 18
    contents.font.shadow = true
    contents.font.out_color = user_color
  end
  #--------------------------------------------------------------------------
  # * Draw Text with Control Characters
  #--------------------------------------------------------------------------
  def draw_text_ex(x, y, text)
    text = convert_escape_characters(text)
    pos = {:x => x, :y => y, :new_x => x, :height => calc_line_height(text)}
    process_character(text.slice!(0, 1), text, pos) until text.empty?
  end
  #--------------------------------------------------------------------------
  # * Sets the width of the window
  #--------------------------------------------------------------------------
  def window_width
    return Graphics.width
  end
  #--------------------------------------------------------------------------
  # * Sets the height of the window
  #--------------------------------------------------------------------------
  def window_height
    return Graphics.height - 72
  end
  #--------------------------------------------------------------------------
  # * Draw the text on the Info Window
  #--------------------------------------------------------------------------
  def draw_text_substance_window(x, y, text)
    #set_font(user_color)
    draw_text_ex(x, y, text)
  end
  #--------------------------------------------------------------------------
  # * Wait After Output of One Character
  #--------------------------------------------------------------------------
  def wait_for_one_character
  end
end