じ☆ve冰风 发表于 2026-8-5 15:58:30

Limited Inventory

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.











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
                              #   $data_weapons
                              #   $data_armors
                              # 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= #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 != item.etype_id
    @equips.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 }; end
def weapons; @weapons.keys.collect {|id| $data_weapons }; end
def armors; @armors.keys.collect {|id| $data_armors }; end
def all_items
    item_a = ITEM_ORDER == 1 ? items : ITEM_ORDER == 2 ? weapons : armors
    item_b = ITEM_ORDER == 1 ? items : ITEM_ORDER == 2 ? weapons : armors
    item_c = ITEM_ORDER == 1 ? items : ITEM_ORDER == 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 = [.max, max_item_number(item)].min
    if container == 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.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
    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
      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 =
    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) + sprintf("%4d", actor.param(param_id)))
    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
    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" + @item_name + "\\C?")
    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" + @item_name + "\\C.")
      @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 =
    else
      swap =
    end
    $game_party.leader.discard_equip(swap)
    $game_party.lose_item(swap, swap)
    $game_party.gain_item(swap, swap)
    $game_storage.lose_item(swap, swap)
    $game_storage.gain_item(swap, swap)
    @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




本贴来自国际rpgmaker官方论坛作者:R_Valkyrie处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/limited-inventory.154353/
页: [1]
查看完整版本: Limited Inventory