R_Valkyrie

Veteran
Veteran
Joined
Sep 3, 2014
Messages
39
Reaction score
20
First Language
Swedish
Primarily Uses
A somewhat simple limited inventory based from my previous Resident Evil scripts. This time it is a bit more generic though for those who doesn't want to make such a game.

LimitedInventory1.pngLimitedInventory2.pngLimitedInventory3.pngLimitedInventory4.png

It's completely free to use and/or edit to your liking.

All you have to do is copy/paste the following script into a new project and read the instructions.
Ruby:
=begin
================================================================================
Limited Inventory 1.0
by R_Valkyrie
--------------------------------------------------------------------------------
You are free to use, edit, and share this in any way you like.
Please credit me if you do.
================================================================================
An item is usable if it has a valid effect. Healing items won't be usable if
you already have full health or don't have a curable state for example.
--------------------------------------------------------------------------------
The Evasion sound effect in the database is used for discarding items.
--------------------------------------------------------------------------------
You can use the following notetags on items/weapons/armors in the database:

  <undiscardable>  #cannot discard this item.
                   #key items cannot be discarded by default.
 
  <hide_number>    #hides the item number.
 
  <variable_id: x> #will draw variable x instead of the item number. Useful
                   #when having ammo for a gun or something.
--------------------------------------------------------------------------------
Use the following scriptline to:

  SceneManager.call(Scene_Storage) #open the storage menu.
 
  $game_party.gain_slot(x)         #increase your inventory.
                                   # x = how many slots you gain.
--------------------------------------------------------------------------------
Use the following scriptline when you want to pick up items:

  $game_party.take_item(x, y) # x = $data_items[id]
                              #     $data_weapons[id]
                              #     $data_armors[id]
                              # y = the amount you get.

Directly after, use the scriptline $game_party.item_taken?() in a conditional
branch. There you can erase the event or have other stuff happen.
================================================================================
=end
module INVENTORY_OPTIONS
  HELP_POS    = true #changes the position of the help window in item/shop menu.
                     # true = bottom, false = top
                   
  DRAW_EQUIP  = true #draws the player's equipment in the status menu.
                     #if false, item name will be colored when equipped instead.
                   
  DRAW_PARAM  = true #draws the atk/def/agi/mat/mdf/luk parameters in the
                     #status menu if set to true.
                   
  MAX_SLOT    = 4    #how many item slots you start with.
 
  MAX_ITEM    = 999  #max number of any one item.
 
  ITEM_ORDER  = [2, 3, 1] #how items are sorted in the menu.
                          # 1 = items, 2 = weapons, 3 = armors
 
  VOCAB_NIL   = "no item" #text for an empty item slot.
 
  VOCAB_SOLD  = "SOLD" #text for bought weapons and armors.
                       #weapons and armors can only be bought once until you
                       #discard or sell it.
 
  COLOR_ITEM  = 1 #color for the number of regular items
 
  COLOR_KEY   = 2 #color for the number of key items
 
  COLOR_VAR   = 3 #color for variable assigned to items.
 
  COLOR_EQUIP = 2 #color for equipped items.
end
#===============================================================================
# Don't edit anything below unless you know what you're doing.
#===============================================================================
class << DataManager
  alias make_inventory_contents make_save_contents
  def make_save_contents
    contents = make_inventory_contents
    contents[:storage] = $game_storage
    return contents
  end
end
class << DataManager
  alias extract_inventory_contents extract_save_contents
  def extract_save_contents(contents)
    extract_inventory_contents(contents)
    $game_storage = contents[:storage]
  end
end
################################################################################
class Game_Actor < Game_Battler
  def change_equip(slot_id, item)
    return if item && equip_slots[slot_id] != item.etype_id
    @equips[slot_id].object = item
    refresh
  end
end
#-------------------------------------------------------------------------------
class Game_Party < Game_Unit
  include INVENTORY_OPTIONS
  alias initialize_inventory_slots initialize
  def initialize
    initialize_inventory_slots
    @occupied_slots  = 0
    @max_slot_number = MAX_SLOT
  end
  def items; @items.keys.collect {|id| $data_items[id] }; end
  def weapons; @weapons.keys.collect {|id| $data_weapons[id] }; end
  def armors; @armors.keys.collect {|id| $data_armors[id] }; end
  def all_items
    item_a = ITEM_ORDER[0] == 1 ? items : ITEM_ORDER[0] == 2 ? weapons : armors
    item_b = ITEM_ORDER[1] == 1 ? items : ITEM_ORDER[1] == 2 ? weapons : armors
    item_c = ITEM_ORDER[2] == 1 ? items : ITEM_ORDER[2] == 2 ? weapons : armors
    item_a + item_b + item_c
  end
  def max_slot_number; @max_slot_number; end
  def max_item_number(item); return MAX_ITEM; end
  def full_inventory?(item)
    max_number = item_number(item) == max_item_number(item)
    (@occupied_slots == @max_slot_number) && (!has_item?(item) || max_number)
  end
  def gain_slot(n); @max_slot_number += n; end
  def gain_item(item, amount, include_equip = false)
    container = item_container(item.class)
    return unless container
    last_number = item_number(item)
    new_number = last_number + amount
    unless has_item?(item)
      return if full_inventory?(item)
      @occupied_slots += 1
    end
    container[item.id] = [[new_number, 0].max, max_item_number(item)].min
    if container[item.id] == 0
      @occupied_slots -= 1
      container.delete(item.id)
    end
    $game_map.need_refresh = true
  end
  def take_item(item, amount)
    SceneManager.call(Scene_ItemTake)
    SceneManager.scene.prepare(item, amount)
    Fiber.yield
  end
  def item_taken?(n = nil)
    @taken = n unless n == nil
    return @taken
  end
end
#-------------------------------------------------------------------------------
class Game_Storage < Game_Party
  def initialize
    init_all_items
    @occupied_slots  = 0
    @max_slot_number = 999
  end
end
################################################################################
class Window_Base < Window
  include INVENTORY_OPTIONS
  def translucent_alpha; return 120; end
  def draw_item_name(item, x, y, enabled = true, width = 172)
    return unless item
    draw_icon(item.icon_index, x, y, enabled)
    change_color(normal_color, enabled)
    if !DRAW_EQUIP && $game_party.leader.equips.include?(item)
      change_color(text_color(COLOR_EQUIP), enabled)
    end
    draw_text(x + 24, y, width, line_height, item.name)
  end
  def draw_variable(item, x, y)
    return unless item.note =~ /<variable_id:/i
    var_number = $game_variables[item.note[/<variable_id:(.*?)>/i, 1].to_i]
    change_color(text_color(COLOR_VAR))
    draw_text(x, y, contents_width - 4, line_height, var_number, 2)
  end
end
#-------------------------------------------------------------------------------
class Window_ItemCategory < Window_HorzCommand
  def make_command_list
    at_storage = SceneManager.scene_is?(Scene_Storage)
    add_command(Vocab::item, :item)
    add_command("Empty", :empty, at_storage)
    add_command(Vocab::save, :save, !$game_system.save_disabled && !at_storage)
    add_command(Vocab::game_end, :game_end, !at_storage)
  end
end
#-------------------------------------------------------------------------------
class Window_ItemList < Window_Selectable
  def col_max; return 1; end
  def item_max; $game_party.max_slot_number; end
  def enable?(item)
    return true if item || SceneManager.scene_is?(Scene_Storage)
  end
  def make_item_list; @data = $game_party.all_items; end
  def draw_item(index)
    item = @data[index]
    rect = item_rect(index)
    slot_color = text_color(15)
    slot_color.alpha = 120
    contents.fill_rect(rect.x + 2, rect.y + 2, rect.width - 4,
      item_height - 4, slot_color)
    reset_font_settings
    if item
      rect.width -= 4
      draw_item_name(item, rect.x, rect.y, enable?(item))
      draw_item_number(rect, item)
    else
      rect.x += 24
      change_color(text_color(8), false)
      draw_text(rect, VOCAB_NIL)
    end
  end
  def draw_item_number(rect, item)
    return if item.note =~ /<hide_number>/i
    draw_variable(item, rect.x, rect.y)
    return if !item.is_a?(RPG::Item) || item.note =~ /<variable_id:/i
    change_color(text_color(item.key_item? ? COLOR_KEY : COLOR_ITEM))
    draw_text(rect, sprintf("%3d", item_number(item)), 2)
  end
  def item_number(item); $game_party.item_number(item); end
end
#-------------------------------------------------------------------------------
class Window_StorageList < Window_ItemList
  def item_max; @data ? @data.size + 1 : 1; end
  def make_item_list; @data = $game_storage.all_items; end
  def item_number(item); $game_storage.item_number(item); end
end
#-------------------------------------------------------------------------------
class Window_ItemCommand < Window_Command
  def window_width; return 120; end
  def make_command_list
    if SceneManager.scene_is?(Scene_ItemTake)
      add_command("Yes", :take_item, @takable)
      add_command("No",  :leave_item)
    else
      add_command(@command,  :use,     @usable)
      add_command("Discard", :discard, @discard)
    end
  end
  def set_command_for(item, valid_use)
    is_equipment = (item.is_a?(RPG::Weapon) || item.is_a?(RPG::Armor))
    @command = is_equipment ? "Equip" : "Use"
    @command = "Unequip" if $game_party.leader.equips.include?(item)
    @usable  = valid_use
    @takable = valid_use
    is_key   = item.is_a?(RPG::Item) && item.key_item?
    if item.note =~ /<undiscardable>/i || is_key
      @discard = false
    else
      @discard = true
    end
  end
end
#-------------------------------------------------------------------------------
class Window_ActorStatus < Window_Base
  def initialize(y, height)
    super(Graphics.width / 2, y, Graphics.width / 2, height)
    refresh
  end
  def draw_actor_health(actor)
    change_color(normal_color, false)
    draw_text(0, 0, contents_width - 4, line_height,
      "/" + sprintf("%4d", actor.mhp), 2)
    change_color(text_color(3))
    change_color(text_color(21)) if actor.hp <= (actor.mhp * 0.75)
    change_color(text_color(20)) if actor.hp <= (actor.mhp * 0.5)
    change_color(text_color(18)) if actor.hp <= (actor.mhp * 0.25)
    draw_text(0, 0, contents_width - 54, line_height,
      sprintf("%4d", actor.hp), 2)
  end
  def draw_actor_equipment(actor)
    return unless DRAW_EQUIP
    draw_horz_line(1.5)
    5.times do |i|
      item = actor.equips[i]
      line_y = line_height * (i + 2)
      if item
        draw_item_name(item, 4, line_y)
        draw_variable(item, 0, line_y)
      else
        change_color(normal_color, false)
        draw_text(28, line_y, contents_width, line_height, "-")
      end
    end
  end
  def draw_actor_parameters(actor)
    return unless DRAW_PARAM
    draw_horz_line(7.5)
    change_color(normal_color, false)
    param_id = [2, 3, 6, 4, 5, 7]
    param_id.size.times do |i|
      px = i < 3 ? 4 : contents_width / 2
      py = i < 3 ? i + 8 : i + 5
      draw_text(px, line_height * py, contents_width, line_height,
        Vocab::param(param_id[i]) + sprintf("%4d", actor.param(param_id[i])))
    end
  end
  def draw_horz_line(y)
    line_color = text_color(8)
    line_color.alpha = translucent_alpha
    contents.fill_rect(0, line_height * y - 1, contents_width, 2, line_color)
  end
  def refresh
    contents.clear
    reset_font_settings
    draw_text(4, 0, contents_width, line_height, $game_party.leader.name)
    draw_actor_health($game_party.leader)
    draw_actor_equipment($game_party.leader)
    draw_actor_parameters($game_party.leader)
  end
end
#-------------------------------------------------------------------------------
class Window_ShopBuy < Window_Selectable
  def window_width; Graphics.width / 2; end
  def enable?(item)
    return false if has_item?(item)
    full = $game_party.full_inventory?(item)
    item && price(item) <= @money && !$game_party.item_max?(item) && !full
  end
  def draw_item(index)
    item = @data[index]
    rect = item_rect(index)
    draw_item_name(item, rect.x, rect.y, enable?(item))
    rect.width -= 4
    if has_item?(item)
      change_color(text_color(18))
      draw_text(rect, VOCAB_SOLD, 2)
    else
      draw_text(rect, price(item), 2)
    end
  end
  def has_item?(item)
    is_equipment = item.is_a?(RPG::Weapon) || item.is_a?(RPG::Armor)
    has_item = $game_party.has_item?(item) || $game_storage.has_item?(item)
    is_equipment && has_item
  end
end
#-------------------------------------------------------------------------------
class Window_ShopNumber < Window_Selectable
  def window_width; Graphics.width / 2; end
  def figures; return 3; end
  def change_number(amount)
    return if @item.is_a?(RPG::Weapon) || @item.is_a?(RPG::Armor)
    @number = [[@number + amount, @max].min, 1].max
  end
end
################################################################################
class Scene_Base; include INVENTORY_OPTIONS; end
#-------------------------------------------------------------------------------
class Scene_Title < Scene_Base
  alias setup_game_extras command_new_game
  def command_new_game
    setup_game_extras
    $game_storage = Game_Storage.new
  end
end
#-------------------------------------------------------------------------------
class Scene_Map < Scene_Base
  def call_menu
    Sound.play_ok
    Input.update
    SceneManager.call(Scene_Item)
  end
end
#-------------------------------------------------------------------------------
class Scene_ItemBase < Scene_MenuBase
  def item_target_actors; [$game_party.leader]; end
end
#-------------------------------------------------------------------------------
class Scene_Item < Scene_ItemBase
  alias start_extra start
  def start
    start_extra
    if HELP_POS
      @help_window.y = Graphics.height - @help_window.height
      @category_window.y -= @help_window.height
      @item_window.y -= @help_window.height
    end
    create_storage_window
    create_command_window
  end
  def create_item_window
    wy = @category_window.y + @category_window.height
    wh = Graphics.height - wy
    @item_window = Window_ItemList.new(0, wy, Graphics.width / 2, wh)
    @item_window.viewport = @viewport
    @item_window.help_window = @help_window
    @item_window.set_handler(:ok,     method(:on_item_ok))
    @item_window.set_handler(:cancel, method(:on_item_cancel))
    @item_window.refresh
  end
  def create_storage_window
    @status_window = Window_ActorStatus.new(@item_window.y, @item_window.height)
  end
  def create_command_window
    @command_window = Window_ItemCommand.new(@item_window.width, @item_window.y)
    @command_window.back_opacity = 255
    @command_window.openness = 0
    @command_window.viewport = Viewport.new
    @command_window.viewport.z = 200
    @command_window.set_handler(:ok,     method(:on_command_ok))
    @command_window.set_handler(:cancel, method(:on_command_cancel))
  end
  def on_category_ok
    case @category_window.current_symbol
    when :item
      @item_window.activate
      @item_window.select_last
    when :empty
      $game_party.max_slot_number.times do |i|
        @item_window.select(i)
        $game_storage.gain_item(item, $game_party.item_number(item))
        $game_party.leader.discard_equip(item)
        $game_party.lose_item(item, $game_party.item_number(item))
      end
      @item_window.unselect
      @item_window.refresh
      @storage_window.refresh
      @category_window.activate
    when :save
      SceneManager.call(Scene_Save)
    when :game_end
      SceneManager.call(Scene_End)
    end
  end
  def on_item_ok
    if item
      valid_use = false
      valid_use = true if $game_party.leader.equippable?(item)
      valid_use = true if item_usable?
      @command_window.set_command_for(item, valid_use)
      @command_window.refresh
      @command_window.open.activate
      @command_window.select(0)
    else
      activate_item_window
    end
  end
  def on_command_ok
    case @command_window.current_symbol
    when :use
      is_equipment = (item.is_a?(RPG::Weapon) || item.is_a?(RPG::Armor))
      if is_equipment && $game_party.leader.equippable?(item)
        Sound.play_equip
        if $game_party.leader.equips.include?(item)
          $game_party.leader.discard_equip(item)
        else
          $game_party.leader.change_equip(item.etype_id, item)
        end
      else
        use_item
      end
      on_command_cancel
    when :discard
      Sound.play_evasion
      $game_party.leader.discard_equip(item)
      $game_party.lose_item(item, $game_party.item_number(item))
      on_command_cancel
    end
  end
  def on_command_cancel
    @status_window.refresh
    @command_window.close
    activate_item_window
  end
end
#-------------------------------------------------------------------------------
class Scene_ItemTake < Scene_Item
  def prepare(item, amount)
    @item = item
    @amount = amount
  end
  alias deactivate_category_window start
  def start
    deactivate_category_window
    @category_window.deactivate
    @category_window.unselect
    @command_window.x = Graphics.width - @command_window.width
    @command_window.y = @help_window.y
    @command_window.opacity = 0
  end
  def post_start
    perform_transition
    Input.update  
    @item_name = sprintf("\\I[%d]", @item.icon_index) + @item.name
    @help_window.set_text("Will you take the \\C[3]" + @item_name + "\\C[0]?")
    takable = !$game_party.full_inventory?(@item)
    @command_window.set_command_for(@item, takable)
    @command_window.refresh
    @command_window.openness = 255
  end
  def on_command_ok
    case @command_window.current_symbol
    when :take_item
      $game_party.gain_item(@item, @amount)
      $game_party.item_taken?(true)
      @help_window.set_text("You have taken \\C[3]" + @item_name + "\\C[0].")
      @item_window.refresh
      @command_window.close.deactivate
      update until @command_window.openness == 0
      Graphics.wait(60)
      return_scene
    when :leave_item
      on_command_cancel
    end
  end
  def on_command_cancel
    $game_party.item_taken?(false)
    @command_window.close.deactivate
    update until @command_window.openness == 0
    return_scene
  end
end
#-------------------------------------------------------------------------------
class Scene_Storage < Scene_Item
  def create_storage_window
    wx = @item_window.width
    wh = @item_window.height
    @storage_window = Window_StorageList.new(wx, @item_window.y, wx, wh)
    @storage_window.viewport = @viewport
    @storage_window.help_window = @help_window
    @storage_window.set_handler(:ok,     method(:on_storage_ok))
    @storage_window.set_handler(:cancel, method(:on_storage_cancel))
    @storage_window.refresh
    @storage_index = 0
  end
  def on_item_ok
    @storage_window.activate
    @storage_window.select(@storage_index)
  end
  def on_storage_ok
    n1 = item ? $game_party.item_number(item) : 0
    n2 = storage_item ? $game_storage.item_number(storage_item) : 0
    if item == storage_item
      swap = [storage_item, n2, nil, 0]
    else
      swap = [storage_item, n2, item, n1]
    end
    $game_party.leader.discard_equip(swap[2])
    $game_party.lose_item(swap[2], swap[3])
    $game_party.gain_item(swap[0], swap[1])
    $game_storage.lose_item(swap[0], swap[1])
    $game_storage.gain_item(swap[2], swap[3])
    @storage_window.refresh
    on_storage_cancel
  end
  def on_storage_cancel
    @storage_index = @storage_window.index
    @storage_window.unselect
    @storage_window.deactivate
    activate_item_window
  end
  def storage_item; @storage_window.item; end
end
#-------------------------------------------------------------------------------
class Scene_Shop < Scene_MenuBase
  def start
    super
    create_help_window
    create_gold_window
    create_command_window
    if HELP_POS
      @help_window.y = Graphics.height - @help_window.height
      @gold_window.y = 0
      @command_window.y = 0
    end
    create_dummy_window
    create_number_window
    create_status_window
    create_buy_window
    create_category_window
    create_sell_window
    @status_window.x = Graphics.width
    @category_window.x = Graphics.width
  end
  def create_dummy_window
    wy = @command_window.y + @command_window.height
    wh = Graphics.height - @help_window.height - @command_window.height
    @dummy_window = Window_Base.new(0, wy, Graphics.width / 2, wh)
    @dummy_window.viewport = @viewport
  end
  def create_sell_window
    wx = Graphics.width / 2
    wh = @dummy_window.height
    @sell_window = Window_ShopSell.new(wx, @category_window.y, wx, wh)
    @sell_window.viewport = @viewport
    @sell_window.help_window = @help_window
    @sell_window.set_handler(:ok,     method(:on_sell_ok))
    @sell_window.set_handler(:cancel, method(:on_sell_cancel))
    @category_window.item_window = @sell_window
  end
  def command_sell
    @sell_window.activate
    @sell_window.select(0)
  end
  def on_sell_ok
    @dummy_window.hide
    @item = @sell_window.item
    @status_window.item = @item
    @number_window.set(@item, max_sell, selling_price, currency_unit)
    @number_window.show.activate
  end
  def on_sell_cancel
    @dummy_window.show
    @sell_window.unselect
    @command_window.activate
    @status_window.item = nil
    @help_window.clear
  end
  def on_number_ok
    Sound.play_shop
    case @command_window.current_symbol
    when :buy
      do_buy(@number_window.number)
    when :sell
      $game_party.leader.discard_equip(@item)
      do_sell(@number_window.number)
    end
    end_number_input
    @gold_window.refresh
    @sell_window.refresh
  end
  def end_number_input
    @number_window.hide
    case @command_window.current_symbol
    when :buy
      activate_buy_window
    when :sell
      activate_sell_window
      @dummy_window.show
    end
  end
end
 
Last edited:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
7,063
Reaction score
9,969
First Language
Indonesian
Primarily Uses
N/A
I see you even have your own scene and window modification. Would be better if you at least put a screenshot or two to see what is changed.

Also, if possible, make an alias for the save contents method. For compatibility purposes.
Ruby:
class << DataManager
  alias liminv_make_save_contents make_save_contents
  def make_save_contents
    contents = liminv_make_save_contents
    contents[:storage] = $game_storage
    return contents
  end
end
 

R_Valkyrie

Veteran
Veteran
Joined
Sep 3, 2014
Messages
39
Reaction score
20
First Language
Swedish
Primarily Uses
I see you even have your own scene and window modification. Would be better if you at least put a screenshot or two to see what is changed.

Also, if possible, make an alias for the save contents method. For compatibility purposes.
Ruby:
class << DataManager
  alias liminv_make_save_contents make_save_contents
  def make_save_contents
    contents = liminv_make_save_contents
    contents[:storage] = $game_storage
    return contents
  end
end
All done now, and thank you for the code :)
 

Ebanyle

what
Veteran
Joined
Sep 2, 2016
Messages
377
Reaction score
238
First Language
Portuguese
Primarily Uses
RMVXA
This looks awesome! I love me some nifty windows xD
 

Latest Threads

Latest Posts

Latest Profile Posts

Hi sweethearts! :kaoluv: Check out my review of @EntangledPear's totally oldskool The Stuff Fairy Tales Are Made Of!
When you spend all day at work distracted by things you want to work on or try in your project and then by the time you get home, you are too mentally tired to concentrate so you just browse the forum instead and think of more things you won’t get to work on for a while.
Time to write some enemy behaviors, here's the stream link for those interested.

Call of duty 1&2 had an interesting cheat prevention method. Between levels the game unloads and reloads the engine dll. If you ever employ this method, make sure to include at least an md5 hash check. Otherwise I can just edit that dll and implant cheats into it.
Hi-Fi Rush is one of the coolest games I've seen in a while. I don't have a way to play it so I watched a friend and wow... I really wish I had a powerful enough computer for it.

Forum statistics

Threads
128,276
Messages
1,193,252
Members
168,731
Latest member
lolcode
Top