=begin
Marrend's Alchemy system.

-Introduction-
This system will allow items to be created by sacrificing items/equipment in
inventory for (usually) better items/equipment. So, basically alchemy.

A recipie can have multiple types of items included in it, and can require
multiple quantities of items. The recipie display is set up to show items
individually, so, keep this in mind when setting up recipies.


-Instructions-
To set up a recipe, go to the database. Select the item/equipment you want
to set up a recipie for. In the notes, write something like...

<recipie>
1, 2, 3, 4, 5
</recipie>

...this. Those numbers represent the IDs of the components. They are assumed to
be the same item type/category as the resulting item. So, an item would have
item components, and equipment would have equipment components.


-Terms of Service-
This script is free to use and edit. If you use the script, please include a
credit to "Marrend" in your credits-file, end-of-game-credits, or however it's
handled. Thanks!
=end


# Adds a "recipie" property to RPG::BaseItem. RPG::Item, RPG::Weapon and
# RPG::Armor are children of this class, and would also be able to access it.
class RPG::BaseItem
  # Make the recipie array.
  def recipie
    notes = note
    if !notes[/<recipie?>(?:[^<]|<[^\/])*<\/recipie>/i]
      @recipie = []
    else
      notes = notes[/<recipie?>(?:[^<]|<[^\/])*<\/recipie?>/i].scan(/(?:!<recipie?>|(.*)\r)/)
      notes.delete_at(0)
      a = notes.join("\r\n")
      @recipie = eval("[#{a}]") rescue []
    end
    return @recipie
  end
  
  # Checks general recipie requirements.
  def can_make?
    total = 0
    i = 0
    while i < @recipie.size
      obj = get_obj(@recipie[i])
      if $game_party.item_number(obj) >= 1
        total += 1
      end
      i += 1
    end
    if total == @recipie.size
      return true
    else
      return false
    end
  end
    
  # Returns an object referenced by a recipe.
  def get_obj(id)
    if self.instance_of?(RPG::Item)
      return $data_items[id]
    elsif self.instance_of?(RPG::Weapon)
      return $data_weapons[id]
    elsif self.instance_of?(RPG::Armor)
      return $data_armors[id]
    end
  end
end

# The window that displays possible recipies.
class Window_RecipieList < Window_Command
  # Start-up proceedure.
  def initialize
    @item = []
    super(0, fitting_height(1))
    select(0)
    activate
  end
  
  # Defines the window's width.
  def window_width
    Graphics.width / 2
  end
  
  # Defines the window's height.
  def window_height
    Graphics.height - fitting_height(1)
  end
  
  # Creates a rectangle suited to text display.
  def item_rect_for_text(index)
    rect = item_rect(index)
    rect.x += 16 + standard_padding
    rect.width -= 8
    rect
  end
  
  # Draws an item on the list.
  def draw_item(index)
    rect = item_rect_for_text(index)
    change_color(normal_color, command_enabled?(index))
    draw_text(rect, command_name(index), alignment)
    if @item.size > 0
      draw_icon(@item[index].icon_index, 0, rect.y)
    end
  end
  
  # Runs through the database to display the recipie list.
  def make_command_list
    # Items.
    i = 1
    while i < $data_items.size
      item = $data_items[i]
      if item.recipie.size != 0
        add_command(item.name, :item, item.can_make?)
        @item.push(item)
      end
      i += 1
    end
    
    # Weapons.
    i = 1
    while i < $data_weapons.size
      item = $data_weapons[i]
      if item.recipie.size != 0
        add_command(item.name, :item, item.can_make?)
        @item.push(item)
      end
      i += 1
    end
    
    # Armor.
    i = 1
    while i < $data_armors.size
      item = $data_armors[i]
      if item.recipie.size != 0
        add_command(item.name, :item, item.can_make?)
        @item.push(item)
      end
      i += 1
    end
  end
  
  # Gets an item id, reffered to by the current cursor position.
  def get_item
    return @item[index]
  end
end

# Window that displays recipie requirements.
class Window_Recipie < Window_Base
  attr_accessor :item
  
  # Start-up procedure.
  def initialize
    super(win_x, fitting_height(1), win_x, win_height)
  end
  
  # Window x-coordinate position.
  def win_x
    Graphics.width / 2
  end
  
  def win_height
    Graphics.height - fitting_height(1)
  end
  
  # Sets the item object.
  def set_recipie(item)
    @item = item
  end
  
  # Defines a rectangle where we draw an ingredient's text.
  def item_rect(index)
    rect = Rect.new(16+standard_padding, line_height*index, contents.width-standard_padding*2, line_height)
    return rect
  end
  
  # Draws a component of the recipie. With the icon!
  def draw_item(index)
    obj = @item.get_obj(@item.recipie[index])
    rect = item_rect(index)
    rect.width = (contents.width - standard_padding * 2) / 2
    draw_icon(obj.icon_index, 0, rect.y)
    change_color(normal_color, $game_party.item_number(obj)>=1)
    draw_text(rect, obj.name)
    change_color(normal_color, $game_party.item_number(obj)>=1)
    rect.width = contents.width-standard_padding*2
    item_num = $game_party.item_number(obj)
    draw_text(rect, "("+item_num.to_s+" → "+(item_num-1).to_s+")", 2)
  end
  
  # Draws all components.
  def draw_all_items
    @item.recipie.size.times { |i| draw_item(i) }
  end
  
  # Update method.
  def update
    super
    contents.clear
    if @item
      draw_all_items
    end
  end
end

# Labels for the windows. Not quite categories, per say, but, simliar.
class Window_Label < Window_Base
  def initialize(text, align=0)
    @text = text
    case align
    when 0
      # Align window on the left side.
      super(0, 0, win_width, fitting_height(1))
    when 1
      # Align window on the right side.
      super(win_width, 0, win_width, fitting_height(1))
    when 2
      # Center window.
      super((Graphics.width-win_width)/2, 0, win_width, fitting_height(1))
    end
  end
  
  # Window width.
  def win_width
    Graphics.width / 2
  end
  
  # Update method.
  def update
    super
    contents.clear
    draw_text(0, 0, win_width, line_height, @text, 1)
  end
end

# Scene processing.
class Scene_Alchemy < Scene_MenuBase
  # Start-up procedure.
  def start
    super
    create_windows
  end
  
  # Creates window objects.
  def create_windows
    @list = Window_RecipieList.new
    @list.set_handler(:ok, method(:on_okay))
    @list.set_handler(:cancel, method(:return_scene))
    
    @recipie = Window_Recipie.new
    @label_a = Window_Label.new("Recipies")
    @label_b = Window_Label.new("Components", 1)
  end
  
  # Process when players press the action button on a recipie.
  def on_okay
    obj = @list.get_item
    $game_party.gain_item(obj, 1)
    for i in obj.recipie
      item = obj.get_obj(i)
      $game_party.lose_item(item, 1)
    end
    @list.refresh
    @list.activate
  end
  
  def update
    super
    item = @list.get_item
    @recipie.set_recipie(item)
  end
end


=begin
Marrend's Ring Menu


--Introduction--
Replaces the standard party menu with a ring menu, similar to that of Secret
of Mana.


--Instructions--
The icon IDs the script uses are placed up front for the sake of convenience.
If you want to adjust what commands/items are on the menu to begin with, that
would need some tweaking to the script, itself.

For reference purposes, the commands this script uses by default for the
party-menu consists of: Item, Skill, Equip, Status, Load, Save, and Quit.
=end

# Icon IDs for commands.
module IconIDs
  # Icon IDs, sorted by command.
  LIST = [260, 143, 160, 121, 230, 117, 175]
  
  # Returns a specified icon.
  def self.icon(index)
    return LIST[index]
  end
  
  # Returns icon associated with "Item".
  def self.item
    return self.icon(0)
  end
  
  # Returns icon associated with "Skill".
  def self.skill
    return self.icon(1)
  end
  
  # Returns icon associated with "Equip".
  def self.equip
    return self.icon(2)
  end
  
  # Returns icon associated with "Status".
  def self.status
    return self.icon(3)
  end
  
  # Retruns icon associated with "Load".
  def self.load
    return self.icon(4)
  end
  
  # Returns icon associated with "Save".
  def self.save
    return self.icon(5)
  end
  
  # Retruns icon associated with "Quit".
  def self.quit
    return self.icon(6)
  end
end
    
# Creates an invisable window that we use to place the icons on, and associates
# commands with said icons.
class Window_Ring < Window_Command
  attr_reader :list
  
  # Start-up process.
  def initialize
    super(window_x, window_y)
    $game_party.menu_actor = $game_party.members[0]
    select(0)
    activate
  end
  
  # Window x position.
  def window_x
    (Graphics.width - window_width) / 2
  end
  
  # Window y position.
  def window_y
    (Graphics.height - window_width) / 2
  end
  
  # Radius of the ring menu.
  def radius
    80
  end
  
  # Window width.
  def window_width
    radius * 2 + 32 + standard_padding*2
  end
    
  # Window height.
  def window_height
    window_width
  end

  # Item rectangle for icons.
  def item_rect(index)
    angle = index.to_f / item_max.to_f * 2 *  Math::PI
    angle -= Math::PI / 2
    icon_x = (radius.to_f * Math.cos(angle)).round
    icon_y = (radius.to_f * Math.sin(angle)).round
    rect = Rect.new(radius+icon_x, radius+icon_y, 32, 32)
    return rect
  end
  
  # Cursor move processing
  def process_cursor_move
    return unless cursor_movable?
    last_index = @index
    cursor_down (Input.trigger?(:DOWN))  if Input.repeat?(:DOWN)
    cursor_up   (Input.trigger?(:UP))    if Input.repeat?(:UP)
    cursor_right(Input.trigger?(:RIGHT)) if Input.repeat?(:RIGHT)
    cursor_left (Input.trigger?(:LEFT))  if Input.repeat?(:LEFT)
    Sound.play_cursor if @index != last_index
  end
  
  # Move cursor down, and...
  def cursor_down(wrap = false)
    cursor_left(wrap)
  end
  
  # Move cursor up, and...
  def cursor_up(wrap = false)
    cursor_right(wrap)
  end
  
  # Move cursor to the right, and...
  def cursor_right(wrap = false)
    index = @index + 1
    if wrap
      if index >= item_max
        select(0)
      else
        select(index)
      end
    end
  end
  
  # Move cursor to the left, and...
  def cursor_left(wrap = false)
    index = @index - 1
    if wrap
      if index < 0
        select(item_max-1)
      else
        select(index)
      end
    end
  end

  # Draws an item.
  def draw_item(index)
    rect = item_rect(index)
    draw_icon(@list[index][:ext], rect.x+4, rect.y+4)
  end
  
  # Draws all items
  def draw_all_items
    item_max.times { |i| draw_item(i) }
  end
  
  # Makes command list.
  def make_command_list
    add_main_commands
    #add_formation_command
    #add_original_commands
    add_other_commands
    #add_game_end_command
  end
  
  # Adds main commands.
  def add_main_commands
    add_command(Vocab::item, :item, true, IconIDs::item)
    add_command(Vocab::skill, :skill, true, IconIDs::skill)
    add_command(Vocab::equip, :equip, true, IconIDs::equip)
    add_command(Vocab::status, :status, true, IconIDs::status)
  end
  
  # Adds other/extranious commands.
  def add_other_commands
    add_command("Load", :load, DataManager.save_file_exists?, IconIDs::load)
    add_command(Vocab::save, :save, !$game_system.save_disabled, IconIDs::save)
    add_command(Vocab::game_end, :game_end, true, IconIDs::quit)
  end
end

# Attaches a help window above the current object/window.
class Window_RingHelp < Window_Base
  # Start-up proces.
  def initialize(obj)
    super(obj.x, obj.y-fitting_height(1), obj.width, fitting_height(1))
    set_text(obj)
  end
  
  # Gets rectangle for drawing text.
  def item_rect
    rect = Rect.new(0, 0, self.width- standard_padding*2, line_height)
    return rect
  end
  
  # Sets object to get text from.
  def set_text(obj)
    @obj = obj.list[obj.index]
  end
  
  # Update method.
  def update
    super
    contents.clear
    change_color(normal_color, @obj[:enabled])
    draw_text(item_rect, @obj[:name], 1)
  end
end

# Scene_Menu overwrites.
class Scene_Menu < Scene_MenuBase
  # Start-up process.
  def start
    super
    create_command_window
    create_gold_window
    #create_status_window
  end
  
  # Creates command window.
  def create_command_window
    @command_window = Window_Ring.new
    @command_window.set_handler(:item,      method(:command_item))
    @command_window.set_handler(:skill,     method(:command_skill))
    @command_window.set_handler(:equip,     method(:command_equip))
    @command_window.set_handler(:status,    method(:command_personal))
    #@command_window.set_handler(:formation, method(:command_formation))
    @command_window.set_handler(:load,      method(:command_load))
    @command_window.set_handler(:save,      method(:command_save))
    @command_window.set_handler(:game_end,  method(:command_game_end))
    @command_window.set_handler(:cancel,    method(:return_scene))
    
    #@command_window = Window_MenuCommand.new
    @help_command = Window_RingHelp.new(@command_window)
    #@command_window.help_window = @help_command
  end
  
  # Calls up skill menu.
  def command_skill
    $game_party.menu_actor = $game_party.members[0]
    SceneManager.call(Scene_Skill)
  end
  
  # Calls up equip menu.
  def command_equip
    $game_party.menu_actor = $game_party.members[0]
    SceneManager.call(Scene_Equip)
  end
  
  # Calls up status.
  def command_personal
    $game_party.menu_actor = $game_party.members[0]
    SceneManager.call(Scene_Status)
  end

  # Loads a game.
  def command_load
    SceneManager.call(Scene_Load)
  end
    
  # Refresh method.
  def update
    super
    @help_command.set_text(@command_window)
  end
end


=begin
Marrend's Fishing Menu.


-Introduction-
Provides a menu with which to attach to a fishing mini-game. The basis for
this script is the Breath of Fire series, more specifically, BoF3.

The intent of this script is to provide a list of fish the player has caught,
and the data associated with that fish. Such as name, a range of length of the
fish, and what the record length of the fish the player has caught.

-Instructions-
The script-call to pull up the menu will be...

SceneManager.call(Scene_Fish)

...as so. Specific data of fish will be up front for custom modification.


-Terms of Service-
This script is free to use and edit. If you use the script, please include a
credit to "Marrend" in your credits-file, end-of-game-credits, or however it's
handled. Thanks!
=end

# Array of FishData. This is the part intended for end-users to customize.
class Game_Fish
  attr_accessor :array
  
  # Initializes the data.
  def initialize
    @array = []
    # Totally going off of BoF3 data, here.
    # Jellyfish. Average length: 20
    @array.push(FishData.new("Jellyfish", 20))
    # Pirana. Average length: 30
    @array.push(FishData.new("Pirana", 30))
    # Puffer. Average length: 35
    @array.push(FishData.new("Puffer", 35))
    # Trout. Average length: 50
    @array.push(FishData.new("Trout", 50))
    # Rainbow Trout. Average length: 50
    @array.push(FishData.new("Rainbow Trout", 50))
    # Red Catfish. Average length: 60
    @array.push(FishData.new("Red Catfish", 60))
    # Bass. Average length: 30
    @array.push(FishData.new("Bass", 30))
    # Martian Squid. Average Length: 60
    @array.push(FishData.new("Martian Squid", 60))
    # Black Bass. Average length: 65
    @array.push(FishData.new("Black Bass", 65))
    # Barandy. Average length: 150
    @array.push(FishData.new("Barandy", 150))
    # Man-o'-War. Average length: 20
    @array.push(FishData.new("Man-o'-War", 20))
    # Flying Fish. Average length: 15
    @array.push(FishData.new("Flying Fish", 15))
    # Blowfish. Average length: 15
    @array.push(FishData.new("Blowfish", 15))
    # Sea Bream. Average length: 30
    @array.push(FishData.new("Sea Bream", 15))
    # Sea Bass. Average length: 45
    @array.push(FishData.new("Sea Bass", 45))
    # Black Porgy. Average length: 45
    @array.push(FishData.new("Black Porgy", 45))
    # Octopus. Average length: 50
    @array.push(FishData.new("Octopus", 50))
    # Angler. Average length: 75
    @array.push(FishData.new("Angler", 75))
    # Devilfish. Average length: 90
    @array.push(FishData.new("Devilfish", 90))
    # Spearfish. Average length: 120
    @array.push(FishData.new("Spearfish", 120))
    # Whale. Average length: 180
    @array.push(FishData.new("Whale", 180))
    # Mackerel. Average length: 50
    @array.push(FishData.new("Mackeral", 50))
    # Manillo. Average lenth: 150
    # Naaaaah.
  end
end

# Fish data class.
class FishData
  # Start-up process.
  def initialize(name="", avg=0, record=0)
    @hash = { :name=> name,
      :max=> (avg.to_f*1.2).ceil,
      :min=> (avg.to_f*0.8).floor,
      :record => record }
  end
    
  # Quick refferal to name.
  def name
    return @hash[:name]
  end
  
  # Quick refferal to maximum length.
  def max_length
    return @hash[:max]
  end
  
  # Quick refferal to minimum length.
  def min_length
    return @hash[:min]
  end
  
  # Quick refferal to record length.
  def record
    return @hash[:record]
  end
  
  # Checks if there is a new record length, and records it.
  def record?(val)
    if val > record
      @hash[:record] = val
    end
  end
end

# Additions/modifications to Game_Party.
class Game_Party < Game_Unit
  attr_accessor :fish
  
  # Start-up process.
  def initialize
    super
    @fish = Game_Fish.new
    @gold = 0
    @steps = 0
    @last_item = Game_BaseItem.new
    @menu_actor_id = 0
    @target_actor_id = 0
    @actors = []
    init_all_items
  end
  
  # Randomizes a catch.
  def catch_fish
    type = rand($game_party.fish.array.size-1)
    fish = $game_party.fish.array[type]
    max = fish.max_length
    min = fish.min_length
    length = rand(max-min)+min
    fish.record?(length)
  end
end

# Window to display the fish-list.
class Window_FishList < Window_Selectable
  # Start-up process.
  def initialize
    super(0, 0, Graphics.width/3, Graphics.height)
  end
  
  # Maximum number of items.
  def item_max
    $game_party.fish.array.size
  end
  
  # Draws an item.
  def draw_item(index)
    rect = item_rect_for_text(index)
    if $game_party.fish.array[index].record > 0
      change_color(normal_color)
      draw_text(rect, $game_party.fish.array[index].name)
    else
      change_color(normal_color, false)
      draw_text(rect, "?????")
    end
  end
  
  # Update method
  def update
    super
    contents.clear
    draw_all_items
  end
end

# Window to display fish data.
class Window_FishData < Window_Base
  # Start-up process.
  def initialize
    super(Graphics.width/3, 0, Graphics.width*2/3, fitting_height(4))
  end
  
  # Draws/prints the info.
  def draw_item(index)
    contents.clear
    fish = $game_party.fish.array[index]
    if fish.record > 0
      draw_text(0, 0, self.width, line_height, "Name: "+fish.name)
      draw_text(0, line_height, self.width, line_height, "Max length: "+fish.max_length.to_s)
      draw_text(0, line_height*2, self.width, line_height, "Min length: "+fish.min_length.to_s)
      draw_text(0, line_height*3, self.width, line_height, "Record: "+fish.record.to_s)
    else
      draw_text(0, 0, self.width, line_height, "Name: ?????")
      draw_text(0, line_height, self.width, line_height, "Max length: ???")
      draw_text(0, line_height*2, self.width, line_height, "Min length: ???")
      draw_text(0, line_height*3, self.width, line_height, "Record: "+fish.record.to_s)
    end
  end
end

# Scene that puts it together.
class Scene_FishList < Scene_MenuBase
  # Start-up process.
  def start
    super
    create_windows
  end
  
  # Creates window objects.
  def create_windows
    @list = Window_FishList.new
    @list.set_handler(:cancel, method(:return_scene))
    @list.select(0)
    @list.activate
    @data = Window_FishData.new
    @data.draw_item(@list.index)
  end
  
  # Update method.
  def update
    super
    @data.draw_item(@list.index)
  end
end