[VXA] Item Drop Ranks

0 Members and 1 Guest are viewing this topic.

*
Rep:
Level 97
2014 Most Unsung Member2014 Best RPG Maker User - Engine2013 Best RPG Maker User (Scripting)2012 Most Mature Member2012 Favorite Staff Member2012 Best RPG Maker User (Scripting)2012 Best MemberSecret Santa 2012 ParticipantProject of the Month winner for July 20092011 Best Use of Avatar and Signature Space2011 Best RPG Maker User (Scripting)2011 Most Mature Member2011 Favourite Staff Member2011 Best Veteran2010 Best RPG Maker User (Scripting)2010 Most Mature Member
Item Drop Ranks
Version: 1.0.2
Author: modern algebra
Date: 28 September, 2012

Version History


  • <Version 1.0.2> 2012.09.28 - Integrated a compatibility fix for Yanfly's Victory Aftermath into the script.
  • <Version 1.0.1> 2012.09.18 - Changed the way the last item drop was saved for the rank dropping item
  • <Version 1.0> 2012.01.22 - Original Release

Description


In effect, this script is designed to make it easy to create random drops. Basically, it allows you to give items, weapons, and armors drop ranks, which are just IDs that you set. Then, you set up other items, called rank distribution items, which you set to contain a particular rank or ranks, and when that rank distribution item is given to the party, it randomly selects an item with that rank and gives that instead.

Please note that if you are distributing more than one of a rankdrop item by an event command, then it will only randomly select one item of the rank and give the amount of it that you set in the event command.

Features

  • An easy way to create random drops which choose from a specified range of items
  • Ability to allow some items to distibute from multiple ranks
  • Retains the name, icon, and description of most recently distributed item, so you can display what was received in messages
  • Rank distribution items also work through enemy drops

Instructions

Paste this script into its own slot in the Script Editor, above Main but below Materials. For instructions on how to use the script, please see the header.

Script


Code: [Select]
#==============================================================================
#    Item Drop Ranks
#    Version: 1.0.2
#    Author: modern algebra (rmrk.net)
#    Date: 28 September, 2012
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Description:
#
#    In effect, this script is designed to make it easy to create random drops.
#   Basically, it allows you to give items, weapons, and armors drop ranks,
#   which are just IDs that you set. Then, you set up other items, called
#   rank distribution items, which you set to contain a particular rank or
#   ranks, and when that rank distribution item is given to the party, it
#   randomly selects an item with that rank and gives that instead.
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Instructions:
#
#    Paste this script into its own slot in the Script Editor, above Main but
#   below Materials.
#
#    As mentioned above, this script essentially works by setting ranks to some
#   items, and then creating dummy items which, when received by the party,
#   randomly select an item of the rank specified and gives it to the party.
#
#    To set a rank for an item, just put the following code in the notebox of
#   the Item, Weapon, or Armor:
#
#      \rank[n]
#        n : a non-negative integer - the rank of this item when distributing
#
#    To create a rank distribution item use the following code in the notebox
#   of the Item, Weapon, or Armor:
#
#      \drop_rank[n]
#        n : a non-negative integer and the rank of items to select from
#
#    You can also set it so that the rank to distribute is actually the value
#   of a variable, vy simply putting a v right before the n. Then, it will
#   take the value of that variable and distribute the corresponding rank.
#``````````````````````````````````````````````````````````````````````````````
#  EXAMPLE:
#
#    The easiest way to explain this script is through an example. Let's say
#   you have four items: Potion; High Potion; Antidote; and a Cure All.
#
#    In the notebox of the Potion and High Potion, you put:
#       \rank[1]
#    In the notebox of the High Potion and Cure All, you put:
#       \rank[2]
#
#    Now, let's say the player opens a chest and you want to give him either a
#   Potion or an Antidote, but not both. You can create a new item in the
#   Database (let's just name it Drop 1), and in its notebox, you put:
#      \drop_rank[1]
#
#    Then, in the chest event, all you need to do give the player Drop 1, and
#   the player will receive either the potion or the antidote.
#
#    Now, let's pretend it is the same situation, except you want the rank of
#   the item dropped to be different depending on how far the player is in the
#   game when he or she approaches the chest. In that case, in your Drop 1
#   notebox, you could put this instead:
#      \drop_rank[v8]
#
#    Then, the rank distributed would depend on the value of Variable 8. So,
#   if the value of Variable 8 is 1 when the player approaches the chest, he or
#   she will receive a Potion or Antidote. If the value of variable 8 is 2,
#   then the player will receive a High Potion or a Cure All.
#``````````````````````````````````````````````````````````````````````````````
#    Now, there is an additional feature to the script - let's say, instead of
#   the player always receiving a rank 1 item, you want the situation to be
#   that 80% of the time, the player will receive a rank 1 item, but 20% of the
#   time you want the player to receive a rank 2 item. You can do that by
#   putting the following code into the notebox of Drop 1:
#
#      \drop_rank[1, 80]
#      \drop_rank[2, 20]
#
#    In other words, you can set it so that a rank distribution item can
#   potentially drop items of different ranks, and you set the percentage by
#   putting another integer after the rank.
#``````````````````````````````````````````````````````````````````````````````
#  Message Codes:
#
#    One last thing to note is that you can use the following message codes:
#      \ii[x] - Shows the icon of Item x.
#      \ni[x] - Shows the name of Item x.
#      \iw[x] - Shows the icon of Weapon x.
#      \nw[x] - Shows the name of Weapon x.
#      \ia[x] - Shows the icon of Armor x.
#      \na[x] - Shows the name of Armor x.
#
#    When you use those codes on a rank distribution item, then it will show
#   the name or icon of the last item distributed by it.
#
#    This is useful so that, in the above chest event, if you want to say what
#   the party got, you can put a message directly below it that makes use of
#   these codes and references the rank distribution item.
#==============================================================================

$imported ||= {}
$imported[:MA_ItemDropRanks] = true

MAIDR_MAX_DATABASE_IWA = 1000

#==============================================================================
# ** RPG::BaseItem
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    new public instance variables - maidr_last_type; maidr_last_id
#    aliased methods - name; icon_index; description
#    new method - maidr_last_item; maidr_drop_rank; maidr_dropping_ranks
#==============================================================================

class RPG::BaseItem
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Public Instance Variables
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  attr_accessor :maidr_last_type
  attr_accessor :maidr_last_id
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Last Distributed Item
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def maidr_last_item
    return case maidr_last_type
    when 0 then $data_items[maidr_last_id]
    when 1 then $data_weapons[maidr_last_id]
    when 2 then $data_armors[maidr_last_id]
    else nil
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Drop Rank
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def maidr_drop_rank
    self.note[/\\RANK\[(\d+)\]/i].nil? ? -1 : $1.to_i
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Dropping Ranks
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def maidr_dropping_ranks
    if !@maidr_dropping_ranks
      @maidr_dropping_ranks = []
      percent_total = 0
      self.note.scan(/\\(DISTRIBUTE|DROP)[ _]RANKS?\[\s*([Vv]?)(\d+)[^\d]*(\d*)\s*\]/i) { |dist, v, rank, perc|
        perc = perc.empty? ? 100 : perc.to_i
        @maidr_dropping_ranks.push([!v.empty?, rank.to_i, perc])
        percent_total += perc
      }
      unless @maidr_dropping_ranks.empty?
        # Make sure percentage adds up to 100.
        variance = 100.0 / percent_total
        @maidr_dropping_ranks.each { |drop| drop[2] = (drop[2].to_f * variance).floor }
        # Alias name, icon_index, and description to give last item
        class << self
          #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          # * Name/Icon Index/Description
          #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          [:name, :icon_index, :description].each { |method_name|
            alias_method(:"maidr_#{method_name}_3hj1", method_name)
            define_method(method_name) { |*args|
              idr = maidr_last_item
              return idr.send(method_name) if idr
              send(:"maidr_#{method_name}_3hj1", *args) # Call Original Method
            }
          }
        end
      end
    end
    @maidr_dropping_ranks
  end
end

#==============================================================================
# *** Data Manager
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    new constant - MAIDR_MAX_DATABASE_IWA
#    aliased method - self.load_database
#==============================================================================

class << DataManager
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Load Database
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias maidr_lddata_3rv6 load_database
  def load_database(*args, &block)
    maidr_lddata_3rv6(*args, &block) # Call Original Method
    # Create a globally accessible hash which holds every item in each rank
    $data_dropranks = {}
    i = 0
    # Go through all Items, Weapons, and Armors
    [$data_items, $data_weapons, $data_armors].each {|data|
      for j in 1...data.size
        next if data[j].nil? || data[j].maidr_drop_rank < 0
        $data_dropranks[data[j].maidr_drop_rank] ||= []
        $data_dropranks[data[j].maidr_drop_rank].push(MAIDR_MAX_DATABASE_IWA*i + j)
      end
      i += 1
    }
    $data_dropranks.default = []
  end
end

#==============================================================================
# ** Game Party
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    aliased method - gain_item
#==============================================================================

class Game_Party
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Gain Item
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias maidr_gainitm_3dk9 gain_item
  def gain_item(item, amount, *args, &block)
    # If not a rank dropping item
    if item.nil? || item.maidr_dropping_ranks.empty? || amount < 1
      maidr_gainitm_3dk9(item, amount, *args, &block) # Call Original Method
    else
      gain_rankdrop_item(item, amount, *args, &block)
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Gain Rank Dropping Item
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def gain_rankdrop_item(item, *args, &block)
    # Select which rank to drop, depending on percentile.
    d = rand(100)
    count = 0
    for i in 0...item.maidr_dropping_ranks.size
      drop = item.maidr_dropping_ranks[i]
      count += drop[2]
      break if d < count
    end
    rank = drop[0] ? $game_variables[drop[1]] : drop[1]
    if $data_dropranks[rank].nil? || $data_dropranks[rank].empty?
      # Accomodate for errors where there are no items of the requested rank
      if !drop[0]
        item.maidr_dropping_ranks.delete(drop) # Delete; no items with rank
        if item.maidr_dropping_ranks.empty?
          p "ERROR: Item Drop Ranks - Rankdrop for #{item.class} #{item.id}: '#{item.maidr_name_3hj1}' fails since no items exist with the rank requested."
          item.maidr_dropping_ranks.push(drop) # Add it back so that this rankdrop item is not received by party next time
        else
          gain_rankdrop_item(item, *args, &block)
        end
      else
        p "ERROR: Item Drop Ranks - Rankdrop for #{item.class} #{item.id}: '#{item.maidr_name_3hj1}' fails since Variable #{drop[1]}: '#{$data_system.variables[drop[1]]}' is equal to #{rank} and no items with that rank exist."
      end
    else
      # Randomly select an item from the array for that rank
      real_drop = $data_dropranks[rank].sample
      # Set details of drop item to those of the actual item dropped
      item.maidr_last_type = real_drop / MAIDR_MAX_DATABASE_IWA
      item.maidr_last_id = real_drop % MAIDR_MAX_DATABASE_IWA
      # Get the actual item
      gain_item(item.maidr_last_item, *args, &block) # Potential Recursion error
    end
  end
end

unless $imported[:ATS_SpecialMessageCodes]
  #============================================================================
  # ** Window_Base
  #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  #  Summary of Changes:
  #    aliased method - convert_escape_characters
  #============================================================================
 
  class Window_Base
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # * Convert Escape Characters
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    alias maidr_convrteschr_2rj6 convert_escape_characters
    def convert_escape_characters(*args, &block)
      result = maidr_convrteschr_2rj6(*args, &block) # Call  Original Method
      # Add ability to use message codes to retrieve icon and name
      result.gsub!(/\eII\[(\d+)\]/i)  { "\eI\[#{$data_items[$1.to_i].icon_index}\]" rescue "" }
      result.gsub!(/\eIW\[(\d+)\]/i)  { "\eI\[#{$data_weapons[$1.to_i].icon_index}\]" rescue "" }
      result.gsub!(/\eIA\[(\d+)\]/i)  { "\eI\[#{$data_armors[$1.to_i].icon_index}\]" rescue "" }
      result.gsub!(/\eNI\[(\d+)\]/i)  { $data_items[$1.to_i].name rescue "" }
      result.gsub!(/\eNW\[(\d+)\]/i)  { $data_weapons[$1.to_i].name rescue "" }
      result.gsub!(/\eNA\[(\d+)\]/i)  { $data_armors[$1.to_i].name rescue "" }
      result
    end
  end
end

# Compatibility Fix for Yanfly's Victory Aftermath
if $imported["YEA-VictoryAftermath"]
  module BattleManager
    #--------------------------------------------------------------------------
    # overwrite method: self.gain_drop_items
    #--------------------------------------------------------------------------
    def self.gain_drop_items
      drops = []
      $game_troop.make_drop_items.each do |item|
        $game_party.gain_item(item, 1)
        drops.push(item.maidr_dropping_ranks.empty? ? item : item.maidr_last_item)
      end
      SceneManager.scene.show_victory_spoils($game_troop.gold_total, drops)
      set_victory_text(@victory_actor, :drops)
      wait_for_message
    end
  end
end

Credit


  • modern algebra

Thanks

  • Valthonis, for alerting me to an incompatibility with Victory Aftermath

Support


Please post in this topic at RMRK to report any errors or to ask any questions regarding this script.

Known Compatibility Issues

Spoiler for Yanfly's Victory Aftermath:
If you are using Yanfly's Victory Aftermath script, then you need to put Item Drop Ranks below it in the script editor. You will also need to update your copy of Item Drop Ranks if you are using a version previous to 1.0.2.
« Last Edit: January 31, 2013, 09:47:50 PM by modern algebra »

*
Rep:
Level 97
2014 Most Unsung Member2014 Best RPG Maker User - Engine2013 Best RPG Maker User (Scripting)2012 Most Mature Member2012 Favorite Staff Member2012 Best RPG Maker User (Scripting)2012 Best MemberSecret Santa 2012 ParticipantProject of the Month winner for July 20092011 Best Use of Avatar and Signature Space2011 Best RPG Maker User (Scripting)2011 Most Mature Member2011 Favourite Staff Member2011 Best Veteran2010 Best RPG Maker User (Scripting)2010 Most Mature Member
I updated this script to 1.0.1 and added a compatibility fix for Yanfly's Victory Aftermath script.