The RPG Maker Resource Kit

RMRK RPG Maker Creation => VX => VX Scripts Database => Topic started by: modern algebra on August 11, 2011, 01:35:31 AM

Title: Perishable Items
Post by: modern algebra on August 11, 2011, 01:35:31 AM
Perishable Items
Version: 1.0
Author: modern algebra
Date: August 10, 2011

Version History



Description


This script allows you to make items (and weapons or armors) that have a lifespan and will turn into another item eventually. Ie, a player could get a warm milk that has special properties if drunk within 60 seconds. Otherwise, it would become a cold milk and be worse. You can also make it so that the item will be destroyed when it perishes.

Features


Screenshots

(https://rmrk.net/proxy.php?request=http%3A%2F%2Fimg717.imageshack.us%2Fimg717%2F1301%2Fperiem.png&hash=5f705e9519ed55ef97e052ede24d9f343c37695d)

Instructions

This script REQUIRES Item Instances Base (http://rmrk.net/index.php/topic,43441.0.html) and MUST be placed below it (though still above Main). If using Zeriab's Dialog System, this script also needs to be below that.

For instructions on using the script, please see the header.

Script


Code: [Select]
#==============================================================================
#    Perishable Items
#    Version: 1.0
#    Author: modern algebra (rmrk.net)
#    Date: August 10, 2011
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Description:
#
#    This script allows you to make items (and weapons or armors) that have a
#   lifespan and will turn into another item eventually. Ie, a player could
#   get a warm milk that has special properties if drunk within 60 seconds.
#   Otherwise, it would become a cold milk and be worse. You can also make it
#   so that the item will be destroyed when it perishes.
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Instructions:
#
#    This script REQUIRES my Instance Items Base script, which you can retrieve
#   from: http://rmrk.net/index.php/topic,43441.0.html. If you want to enable
#   the feature to show a message when items perish, then you will need
#   Zeriab's Dialog System, from: http://rmrk.net/index.php/topic,24828.0.html
#
#    Paste this script into its own slot somewhere above Main and below the
#   Instance Items Base and Dialog System (if using) scripts.
#
#    To set an item to perish, all you need to do is put the following code in
#   its notebox:
#        \perish[time, replacement]
#          time        : the number of seconds from its creation before the
#                       item perishes
#          replacement : the item perished into. It is a letter representing
#                       type of item (I => Item; W => Weapon; A => Armor)
#                       succeeded by the ID. So I12 would be the 12 item in the
#                       database, A4 would be the 4th armor in the database,
#                       etc. This can be excluded altogether and then the
#                       perishing item will simply be destroyed.
#
#  EXAMPLES:
#        \perish[120, W5]
#      An item with this in its notebox would perish 2 minutes after being
#     received, and it would turn into the 5th weapon in the database.
#
#        \perish[80]
#      An item with this in its notebox would be destroyed after 80 seconds.
#
#    If you have the Dialog system and opt to show a message, then you can
#   customize the message that is shown with the following code in the
#   perishing item's notebox:
#        \perish_message[text]
#          text : the message you want displayed. The code: \oi will be
#                replaced with the name of the perishing item wile \ni will be
#                replaced with the name of the new item.
#
#    You can also set which scenes the script updates in, what SE plays when an
#   item perishes, whether a message is shown and various aspects of that. Read
#   the instructions in the Editable Region at line 62.
#==============================================================================

if $imported && $imported["MAInstanceItemsBase"]
$imported["MAPerishableItems"] = true

#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
#  EDITABLE REGION
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#  In this array, put the scenes in which the perishing timer will count down.
# Ie. if you want opening the menu to pause the perish timer, then don't put it
# in the array.
MAPI_PERISH_COUNTDOWN_SCENES = [Scene_Map]
#  SE to be played when an item perishes. If you want to also set volume and
# pitch, you can set it as an array: ["filename", volume, pitch]
MAPI_ITEM_PERISH_SE = ["Down"]
#  Whether to show a message when messages perish. If true, you need to put
# Zeriab's Dialog system somewhere above this script in the editor. It can be
# found at:
MAPI_SHOW_MESSAGE = true
  # The following options only apply if MAPI_USE_DIALOG is true
  MAPI_USE_DIM_BACKGROUND = false # Whether to dim the background when showing
  MAPI_WINDOW_OPACITY = 200 # The opacity of the window that shows the message
  # The alignment of the text in the window. 0 => Left, 1 => Centre; 2 => Right
  MAPI_WINDOW_ALIGN = 1
  #  The default message format for perishing. \\OI will be replaced by the
  # name of the perishing item while \\NI will be replaced by the name of the
  # replacing item.
  MAPI_VOCAB_PERISH_INTO = "Your \\oi has become \\ni!"
  #  Same as above, but MAPI_VOCAB_PERISH_DESTROY is for when the perishing
  # item doesn't turn into anything and is simply destroyed.
  MAPI_VOCAB_PERISH_DESTROY = "Your \\oi has perished!"
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#  END EDITABLE_REGION
#//////////////////////////////////////////////////////////////////////////////

#==============================================================================
# ** RPG::BaseItem
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    new method - get_perishablity
#==============================================================================

class RPG::BaseItem
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * CONSTANTS
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  MA_INSTANCE_CHECKS << /\\PERISH\[\s*\d+[,\s]*[WAI]?\d*\s*\]/i
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Perish Time
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def get_perishability
    if !@perishability
      @perishability = [-1, -1, -1]
      if self.note[/\\PERISH\[\s*(\d+)[,\s]*([WAI]?)(\d*)\s*\]/i] != nil
        type = case $2.upcase
        when "I" then 0
        when "W" then 1
        when "A" then 2
        else
          type = -1
        end
        @perishability = [$1.to_i, type, $3.empty? ? -1 : $3.to_i]
      end
    end
    return @perishability
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Perish Message
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def perish_message
    return @perish_message if @perish_message
    if self.note[/\\PERISH_MESSAGE\[(.+?)\]/im]
      @perish_message = $1.gsub (/\r\n/) { " " }
      return @perish_message
    end
    perish = get_perishability
    return perish[1] != -1 && perish[2] != -1 ? MAPI_VOCAB_PERISH_INTO : MAPI_VOCAB_PERISH_DESTROY
  end
end

#==============================================================================
# *** II_BaseItem
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    new attributes - perish_time; perish_item_type; perish_item_id
#    aliased method - setup
#==============================================================================

module II_BaseItem
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Public Instance Variables
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  attr_accessor :perish_time      # The number of frames before this perishes
  attr_accessor :perish_item_type # The type (Item, Weapon, Armor) it becomes
  attr_accessor :perish_item_id   # Once perished, ID of the item it becomes
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Setup
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias malg_iiperish_setup_8gm2 setup
  def setup (item, *args, &block)
    malg_iiperish_setup_8gm2 (item, *args, &block) # Run Original Method
    @perish_time, @perish_item_type, @perish_item_id = *item.get_perishability
    $game_system.perishing_items << self if self.perish_time > 0
  end
end

#==============================================================================
# ** Game_System
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    new attribute - perishing_items
#==============================================================================

class Game_System
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Public Instance Variables
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  attr_accessor :perishing_items
  attr_accessor :perish_frame_timer
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Object Initialization
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias mg_perishit_initz_5tc2 initialize
  def initialize (*args, &block)
    @perishing_items = []
    @perish_frame_timer = 0
    mg_perishit_initz_5tc2 (*args, &block) # Run Original Method
  end
end

#==============================================================================
#  Scene Base
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    aliased method - update
#==============================================================================

class Scene_Base
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Update
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias moalg_perishitem_upd_6yh1 update
  def update (*args, &block)
    # Run Original Method
    moalg_perishitem_upd_6yh1 (*args, &block)
    return unless MAPI_PERISH_COUNTDOWN_SCENES.include? (self.class)
    $game_system.perish_frame_timer += 1
    return if $game_system.perish_frame_timer < 60
    lines = []
    perished = []
    # Update perishables every second
    $game_system.perishing_items.each { |item|
      item.perish_time -= 1
      if item.perish_time <= 0
        data_type = case item
        when RPG::Item then $data_items
        when RPG::Weapon then $data_weapons
        when RPG::Armor then $data_armors
        end
        # Convert (or Destroy) the Item
        if $game_party.has_item? (item, true)
          perish_msg = item.perish_message.gsub (/\\[Oo][Ii]/) { item.name }
          if item.perish_item_type != -1 && item.perish_item_id > 0
            item2_data = $game_system.instance_items[item.perish_item_type]
            if item2_data.size > item.perish_item_id
              item2 = item2_data[item.perish_item_id]
              $game_party.gain_item (item2, 1)
              perish_msg.gsub! (/\\[Nn][Ii]/) { item2.name }
              # If the perishing item was equipped
              if $game_party.item_number (item) <= 0 && !item2.is_a? (RPG::Item) && data_type == item2_data
                for actor in $game_party.members
                  index = actor.equips.index (item)
                  if index != nil
                    actor.change_equip (index, item2) if actor.equippable? (item2)
                    break
                  end
                end
              end
            end
          end
          # Lose and destroy the perished item
          $game_party.ii_destroy_lost_instances = true
          $game_party.lose_item (item, 1, true)
          $game_party.ii_destroy_lost_instances = false
        else
          data_type.destroy_instance (item.id)
        end
        lines << perish_msg if perish_msg
        perished << item
      end
    }
    perished.each { |item| $game_system.perishing_items.delete (item) }
    unless lines.empty?
      # Play SE
      if !MAPI_ITEM_PERISH_SE.empty?
        se = MAPI_ITEM_PERISH_SE.is_a? (String) ? [MAPI_ITEM_PERISH_SE] : MAPI_ITEM_PERISH_SE
        RPG::SE.new (*se).play
      end
      Dialog_PerishedItems.show (lines) if Object.constants.include? ("Dialog_PerishedItems")
    end
    $game_system.perish_frame_timer = 0 # Reset Frame Timer
  end
end

if MAPI_SHOW_MESSAGE && Object.constants.include? ("Dialog") # If the Dialog system is installed
#==============================================================================
# ** Window_PerishedItems
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  This window just shows all items that perished this frame
#==============================================================================

class Window_PerishedItems < Window_Base
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Object Initialize
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def initialize (lines)
    hght = 32 + (lines.size * WLH)
    super (0, (Graphics.height - hght) / 2, Graphics.width, hght)
    self.opacity = MAPI_WINDOW_OPACITY
    for i in 0...lines.size
      draw_line (i*WLH, lines[i])
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Draw Line
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def draw_line (y, line)
    self.contents.draw_text (0, y, contents.width, WLH, line, MAPI_WINDOW_ALIGN)
  end
end

#==============================================================================
# ** Dialog_PerishedItems
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  This dialog processes showing perished items
#==============================================================================

class Dialog_PerishedItems < Dialog
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Object Initialization
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def initialize (lines)
    super ()
    @lines = lines
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Create Window
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def main_window
    @notify_window = Window_PerishedItems.new (@lines)
    @notify_window.z = STARTING_Z_VALUE + 1
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Dispose Windows
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def main_dispose
    @notify_window.dispose
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Frame Update
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def update
  if Input.trigger?(Input::B) || Input.trigger? (Input::C)
      Sound.play_cancel
    mark_to_close
  end
  end
  unless MAPI_USE_DIM_BACKGROUND
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # * Create Background
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def create_background
      @background_sprite = Sprite.new # Create dummy sprite for disposing
    end
  end
end

end

else
  p "Perishable Items requires the Item Instances Base script, which can be found at RMRK:\nhttp://rmrk.net/index.php/topic,43441.0.html"
end

Credit



Thanks


Support


Please post in this topic at RMRK if you have any bug reports or suggestions.

Known Compatibility Issues

Perishable Items REQUIRES Instance Items Base (http://rmrk.net/index.php/topic,43441.0.html) and must be below it (though still above Main). If using Zeriab's Dialog System, this script also needs to be below that.

If you are using any custom scenes that you add to the timer array, then those scripts also need to be above Perishable Items in order in the Script Editor.

Demo


Mitsarugi made this demo (http://www.mediafire.com/?00a25pjbdi3d6nq) so you can see how the script works.
Title: Re: Perishable Items
Post by: Mitsarugi on August 11, 2011, 03:43:58 PM
Demo made for this cool idea ^^ , nice for ice cubes (need to find that icon set tho -_-') or plants that grow.
here you go :   http://www.mediafire.com/?00a25pjbdi3d6nq
Title: Re: Perishable Items
Post by: modern algebra on August 11, 2011, 04:01:58 PM
Thanks for making the demo! I'll add it to the first post.
Title: Re: Perishable Items
Post by: Mitsarugi on August 11, 2011, 04:04:18 PM
Thanks for making the demo! I'll add it to the first post.
no problem ;p , just helping where i can ^^


EDIT: i did find out that you have to press Enter to close the message window coz it freezes the game, you should let it disappear in some seconds ;p
Title: Re: Perishable Items
Post by: cozziekuns on August 14, 2011, 10:39:28 PM
Wow, Zeriab's dialog system is so handy! I'll definitiely be using it more often; not sure why I hadn't heard of it till now!

Great script too, MA.

@Mitsarugi:

Code: [Select]

COZ_MA_MITSA_FRAME_COUNT = 256 # Frames before the window disposes

#==============================================================================
# ** Dialog_PerishedItems
#==============================================================================

class Dialog_PerishedItems < Dialog
 
   alias coz_mitsu_dpi_dialog_initialize initialize
   def initialize(lines, *args)
    coz_mitsu_dpi_dialog_initialize(lines, *args)
    @frames = 0
  end
 
  alias coz_mitsu_dpi_dialog_update update
  def update
    @frames += 1
    coz_mitsu_dpi_dialog_update
    mark_to_close if @frames == COZ_MA_MITSU_FRAME_COUNT
  end
end
Title: Re: Perishable Items
Post by: Mitsarugi on August 15, 2011, 12:33:03 AM
Wow, Zeriab's dialog system is so handy! I'll definitiely be using it more often; not sure why I hadn't heard of it till now!

Great script too, MA.

@Mitsarugi:

Code: [Select]

COZ_MA_MITSA_FRAME_COUNT = 256 # Frames before the window disposes

#==============================================================================
# ** Dialog_PerishedItems
#==============================================================================

class Dialog_PerishedItems < Dialog
 
   alias coz_mitsu_dpi_dialog_initialize initialize
   def initialize(lines, *args)
    coz_mitsu_dpi_dialog_initialize(lines, *args)
    @frames = 0
  end
 
  alias coz_mitsu_dpi_dialog_update update
  def update
    @frames += 1
    coz_mitsu_dpi_dialog_update
    mark_to_close if @frames == COZ_MA_MITSU_FRAME_COUNT
  end
end
thanks ^^ this might even help others ;p