Jump to content

Recommended Posts

I am identifying problematic methods and things that can be made more flexible and intuitive.

What kinds of things do you think can be written "better"?

 

One thing that I am currently not sure about is how inventory counts are done.

 

Rather than simply adding up all of the slots, I increase and decrease these counts ONLY when you add/remove an item. The idea is that the only way for an item to get in or out of the inventory is through "gain item" and "lose item".

 

This is meant solely for performance reasons, and relies on the above assumptions to be true.

Share this post


Link to post
Share on other sites

Well personally, I think how the inventory is stored is a bit counter intuitive and messy. I would have just had Game_Inventory have one big array that was sorted and filtered as necessary, but performance could be an issue. The thing is, it might actually be faster to do things that way, depending on how ruby is optimized. For example, a block could be 'compiled' once before the loop, the loop it's self run in machine code since it's a built in function, as opposed to all of the looking up and interpreting it would have to do bouncing around a lot of classes. I am speculating though.

Share this post


Link to post
Share on other sites

The reason why I implemented it that way is because the count is re-calculated when you

 

-add an item

-remove an item

-fetch the inventory count

 

This applies to individual slots as well, where you loop over all of the stacks although on average this is not an issue because a single slot wouldn't have millions of stacks to make any significant impact on performance.

 

But having to calculate the count for the entire inventory sounds like it may cause problems.

I never actually benchmarked it to determine when it actually becomes a problem though.

Edited by Tsukihime

Share this post


Link to post
Share on other sites

It looks to me like there is a lot of redundancy and redirection in there I think. I understand your intention, it just adds a layer of complexity to it that is a little bit hard to understand. Also you don't actually seem to use Game_InventorySlot's weight count anymore, and only use the item count once. I donno. In any case it works, but there seems to be a few things in there that are left overs from old versions or never implemented. It just could use a bit of a clean up.

Share this post


Link to post
Share on other sites

Definitely, I think when I started adding/changing stuff, unneeded stuff didn't get cleared out.

 

I will start by removing the explicit "count" instance variable and replace it with a getter method that will just sum up all of the slots' counts. This should take off several methods that are no longer needed such as those "update" methods.

 

After that I'll throw some stress tests at it and see if having a million stacks of items will cause an issue.

Share this post


Link to post
Share on other sites

BTW, if you are interested, here are some tweaks/add-ons I have made for inventory plus:

 

 

#========================================================================
# * Make new item subclasses
#   Moving make_item into a module so objects can be created
#   outside the party inventory.
#========================================================================

module ItemMaker

  def self.make_item(item, i)
    if item.is_a?(BaseItem)
      obj = Marshal.load(Marshal.dump(item)) # old deep clone hack
      obj.instance_variable_set(:@index, i) # set new index
      return obj
    elsif item.note.downcase =~ /^/i
      type = item.is_a?(RPG::Item)   ? "Item_"   :
             item.is_a?(RPG::Armor)  ? "Armor_"  :
             item.is_a?(RPG::Weapon) ? "Weapon_" :
             nil 
      unless type.nil?
        cls = Kernel.const_get("Game_" + type + $1.capitalize)
        unless cls.nil?
          return cls.new(item, i)
        end
      end
    elsif $imported['KRX-Enchantment'] && item.is_a?(RPG::Armor) && item.is_rune?
      cls = Kernel.const_get("Game_Armor_Rune")
      unless cls.nil?
        return cls.new(item, i)
      end
    end
    return Game_Item.new(item, i) if item.is_a?(RPG::Item)
    return Game_Weapon.new(item, i) if item.is_a?(RPG::Weapon)
    return Game_Armor.new(item, i) if item.is_a?(RPG::Armor)
  end
  
end

class Game_Temp
  
  attr_accessor :last_item_got
  
end

class Game_InventorySlot

  def make_item(item, i)
    obj = ItemMaker.make_item(item, i)
    $game_temp.last_item_got = obj
    @stacks[i] = obj
  end

end

#========================================================================
# * Code for running a method when the item is used.
#========================================================================

class Game_Temp
  
  attr_accessor :last_item_used
  
end

module BaseItem
  
  def on_use
    $game_temp.last_item_used = self
  end
  
end

class Game_Battler < Game_BattlerBase
  
  alias_method :use_item_ip_base, :use_item
  def use_item(item)
    if item.is_a?(BaseItem)
      item.on_use
    end
    use_item_ip_base(item)
  end
  
end

#========================================================================
# * Add method to choose when to stack with stuff
#========================================================================

class Game_InventorySlot
  
  # gets the first available stack to add item to
  def get_stack(item)
    (0 .. @stacks.size ).find do |k| 
      @stacks[k].nil? || (@stacks[k].can_add? && @stacks[k].stack_with(item))
    end
  end
  
end

module BaseItem
  
  def stack_with(item)
    return false unless item
    item.id == self.id 
  end

end

#========================================================================
# * Let items have a new method to see if they can be removed
#   Also group equipment to allow multi-use equipment slots.
#========================================================================

# BaseItem so compatible with Actor Inventory
module BaseItem
  
  def can_remove?
    return true
  end
  
end

class RPG::EquipItem
  
  def equip_groups
    unless @equip_groups 
      @equip_groups = []
      self.note.split(/[\r\n]+/).each do |line|
        if line =~ /\s*/i
          @equip_groups.push($1.downcase)
        end
      end
    end
    return @equip_groups 
  end
  
end

module EquipItem
  
  def equip_setup(item, index)
    for i in 0...8
      @per_params[i] = @per_params[i] * (rand * 2)
    end
  end
  
end

class Game_Actor < Game_Battler

  alias_method :equip_change_ok_ip_base?, :equip_change_ok?
  def equip_change_ok?(slot_id)
    return true if @equips[slot_id].object.nil?
    return false unless @equips[slot_id].object.can_remove?
    return equip_change_ok_ip_base?(slot_id)
  end
  
  def enable_equip?(item, slot_id)
    return true unless item.is_a?(Game_Weapon) || item.is_a?(Game_Armor)
    e=[]
    @equips.each_with_index do |eq, i|
      next if i == slot_id
      e |= eq.object.equip_groups if eq.object.is_a?(Game_Armor) 
    end
    return false if item.equip_groups.any? {|g| e.include?(g)}
    return true
  end
  
  def optimize_equipments
    $game_temp.eds_actor = self
    @optimize_clear = true
    clear_equipments
    @optimize_clear = false
    e = []
    equip_slots.size.times do |i|
      next if !equip_change_ok?(i)
      next unless can_optimize?(i)
      items = $game_party.equip_items.select do |item|
        item.etype_id == equip_slots[i] &&
        equippable?(item) && item.performance >= 0 && 
        !item.equip_groups.any? {|g| e.include?(g)}
      end
      change_equip(i, items.max_by {|item| item.performance })
      e |= @equips[i].object.equip_groups unless @equips[i].object.nil?
    end
    $game_temp.eds_actor = nil
  end
  
end

class Window_EquipItem < Window_ItemList
  
  def enable?(item)
    return @actor.enable_equip?(item, @slot_id)
  end
  
end

#==============================================================================
# * Shop goods use Inventory Plus objects.
#   That way they always give the correct name/icon/whatever
#==============================================================================

class Window_ShopBuy < Window_Selectable

  #--------------------------------------------------------------------------
  # * Create Item List
  #--------------------------------------------------------------------------
  def make_item_list
    @data = []
    @price = {}
    @shop_goods.each do |goods|
      case goods[0]
      when 0;  item = $data_items[goods[1]]
      when 1;  item = $data_weapons[goods[1]]
      when 2;  item = $data_armors[goods[1]]
      end
      if item
        object = ItemMaker::make_item(item, nil)
        @data.push(object)
        @price[object] = goods[2] == 0 ? item.price : goods[3]
      end
    end
  end
  
end

#========================================================================
# * Number each item for age sorting
#========================================================================

module BaseItem

  attr_reader :item_age_sort
  
  alias_method :add_amount_age_sort_base, :add_amount
  def add_amount(amt)
    unless @item_age_sort == $game_system.total_items
      @item_age_sort = $game_system.total_items += 1
    end
    #puts(@item_age_sort)
    add_amount_age_sort_base(amt)
  end
  
end

class Game_System
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :total_items
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  alias_method :initialize_sys_age_sort_base, :initialize
  def initialize
    initialize_sys_age_sort_base
    @total_items = 0
  end
  
end

 

 

Oh btw, why do you overwrite the class method for items using the BaseItem module? Some of my code required me to redefine it to call the super method again... notably this:

 

 

#========================================================================
# * Module for randomizeing item apperence
#========================================================================

module RandomizedItem
  
  attr_reader :real_name
  
  def randomize(index)
    info = $game_party.get_type_info(self, index)
    if (defined? icon_hue)
      @icon_hue = ($data_items[id].icon_hue + info[0]) % 360
    end
    @icon_index = info[1]
    @name = info[2]
    @real_name = info[3]
  end

  def name
    return self.identified? ? @real_name : @name
  end
  
end

# Gets proper class
module BaseItem
  
  def class
    super
  end
  
end

# New methods to get or generate random names/icons/icon hues
class Game_Party < Game_Unit
  
  def get_type_info(item, index)
    type = item.class.name.to_sym
    typeinfo = ((@existing_type_info ||= {})[type] ||= [])
    unless typeinfo[index]
      info = []
      info[0] = (rand(16)*22.5).to_i
      info[1] = item.class.const_get("RANDOM_ICONS").sample
      typenames = ((@type_names_left ||= {})[type] ||= item.class.const_get("RANDOM_NAMES").shuffle)
      info[2] = (typenames.empty? ? "Unknown"
                 : typenames.pop) + " " + item.class.const_get("TYPE_NAME")
      info[3] = item.name
      typeinfo[index] = info
      return info
    end
    return typeinfo[index]
  end
    
end

 

 

Hehe... needless to say I do a lot of weird item subclassing and stuff.

Edited by KilloZapit

Share this post


Link to post
Share on other sites

Oh btw, why do you overwrite the class method for items using the BaseItem module? Some of my code required me to redefine it to call the super method again... notably this:

At this point it's most accurate to say "don't know"

It doesn't even look like it's being used, seeing how I randomly put

attr_reader :class
Must have thought it was "necessary" or something.

 

The (unpublished) revised script currently removes the following features from the "base" inventory system

 

-item limits

-weight limits

 

They will be moved into separate add-on scripts. People that don't need limits don't need to bother with it.

 

The Game_Inventory and Game_InventorySlot objects will remain as they were originally designed

The inventory object is an abstraction of a party's inventory, and each inventory slot holds a "type" of object based on their class.

 

I am considering scrapping the Game_CustItem class and simply overwriting the methods defined in BaseItem to suit my purposes. After all, if other scripts are working with the inventory, they presumably will be using BaseItem objects and not these CustItem objects anyways.

 

The idea that "overwriting is bad" in this case wouldn't hold. It WOULD break compatibility with any scripts that rely on the default BaseItem implementation, but I doubt they would have been compatible anyways. Rather than deal with RPG::Weapon and Game_Weapon objects and doing all sorts of ugly backwards compatibility hacks, I can just have all equips wrapped when they are pulled from the database and into a BaseItem object.

 

This would allow me to remove all of the excess class overwrites/aliases that are only there because I wanted to work with CustItem objects.

 

I wonder if these Game_Weapon, Game_Armor, and Game_Item classes are also doing too much.

They copy all of the instance variables from the RPG "template" objects, but then do things like keeping track of stacks which is inherently something that the inventory slot should be doing. A Potion doesn't need to know how many copies of it does it hold.

 

Most importantly, there is this script: http://forums.rpgmakerweb.com/index.php?/topic/7431-ses-instance-items-v13-february-17th-bugfix-for-anti-bloat-bugfix-for-main-script/

 

The inventory system doesn't need to handle instance of equips; it just needs to hold them.

EDIT: then again, I'd rather have a stand-alone system...hmm this is tricky.

Edited by Tsukihime

Share this post


Link to post
Share on other sites

Well I kind of think Game_Weapon, Game_Armor, and Game_Item should keep track of the quantity number of that instance of the object for sure. I kind of think it might be better to move away from using database ids as much in relation to stacks and things. I actually have started experimenting with using database objects as templates for item types rather then individual objects. I have a spell scroll object for example that can hold a number of different one use spells on it, and only uses one database id. I was thinking of making potion and herb objects that choose one or two effects from it's effect list per instance.

I guess I could give them dynamic ids if I wanted though.

 

Oh and in relation to copying instance variables and stuff, I made this class not to long ago:

 

 

class Game_Custom_Skill
  attr_accessor :installs
  attr_writer :name
  
  def initialize(skill, installs = nil)
    @id = skill.id
    @installs = (installs || [])
  end
  
  def name
    @name || $data_skills[@id].name
  end
  
  def method_missing(method, *args)
    skill = $data_skills[@id]
    if skill.respond_to?(method)
      skill.send(method, *args)
    else
      super
    end
  end 

end

 

 

I suppose with some work it could be expanded to some sort of general delegation method, or something.

Share this post


Link to post
Share on other sites

Honestly I kinda think it would be better if the player just moved slower if you were over encumbered rather then having a hard limit.

 

That's exactly what I need! Like disable sprinting when being overencumbered instead of having the hard limit, perhaps accompanied by a quick notification when you pass the limit.

Would anyone be able to help me out?

 

Also - but this isn't nearly as important to me as my first request - would it be possible to link a skill to this script? For example, a character acquired a 'strong back' skill/perk and it upgrades his carrying capacity from 200 to 250.

 

Thanks in advance for any advice/help!

Share this post


Link to post
Share on other sites

Aha!

There is also a 'limit_reached?' method in Game_Inventory, which has the same code in it.

Also I changed the 'can_add_amount?' in both Game_Inventory and Game_InventorySlot into:

 def can_add_amount?(item)
   return [max_items - @item_count, 0].max
  end

Added 'overweight?' method in Game_Party. Now I can use that as a condition in a parallel process common event. Fantastic.

 

Thanks for the help!

 

May I ask how exactly you set up the overweight method?

 

Edit: Excuse the double post.

Edited by masterp

Share this post


Link to post
Share on other sites

This is all I added to Game_Party:

def overweight?
  weight > max_weight
end

Here's the logic I use in a parallel process common event:

$game_party.overweight? == true

If true,

> add conditon "Encumbered"

> set move route: [slow player speed]

 

Else,

 If condition "Encumbered" == true

  > remove condition "Encumbered"

  > set move route: [normal player speed]

 

You can set up the "Encubered" state to give whatever debuffs you want.

This is the way I use it, there could be more elegant way to make it 100% script.

 

Hope this helps!

Share this post


Link to post
Share on other sites

Hi, is there anyway to make the max limit or weight to an in-game variable so that it can increase in game?

Share this post


Link to post
Share on other sites

This is all I added to Game_Party:

def overweight?
  weight > max_weight
end

Here's the logic I use in a parallel process common event:

$game_party.overweight? == true

If true,

> add conditon "Encumbered"

> set move route: [slow player speed]

 

Else,

 If condition "Encumbered" == true

  > remove condition "Encumbered"

  > set move route: [normal player speed]

 

You can set up the "Encubered" state to give whatever debuffs you want.

This is the way I use it, there could be more elegant way to make it 100% script.

 

Hope this helps!

This is great! 

 

However, I have some trouble setting up the common event, would it be possible to share a screenshot, perhaps? Thanks in advance!

Share this post


Link to post
Share on other sites

Here's a screenshot of the common event I use:

 

post-21029-0-41182900-1369072079_thumb.png

 

I had other stuff in there, but I deleted everything except the delay (prevents lag) so you can clearly see the overweight check.

Of course, you can have anything under the conditional branches, whatever fits your project!

 

If you set up a switch to toggle the parallel process, remember to turn it on to actually run the code in-game.

Share this post


Link to post
Share on other sites

It works! Thanks man, you really helped me out there!

 

Now I just have to figure out a way to make the max carrying capacity go up every 5 levels or so.

Share this post


Link to post
Share on other sites

Great looking script, just a few questions(on my phone, hard to check if they've already been asked)

Firstly can you make it so that your inventory size can increase throughout the game (i.e. you get a bigger bag)

Second is there any way to make it so in the item menu scene it so the "WT x/9999" window is in the lower right corner as oppose to the upper

And last I don't know what I'm doing wrong but "count_by_stack" doesn't seem to be working unless I interpreted its use wrong

Share this post


Link to post
Share on other sites

This script was pretty much experimental and so it is hard to write add-ons.

It combined multiple concepts together:

 

-Inventory management

-Item management, like stacks and weights and stuff

-Instance items

 

Which is a pretty bad idea.

Share this post


Link to post
Share on other sites

this is a great script, tought I only use it for the item weight thingy.  I found a weird incompatibility with Yami's Battle Order. When I try to use an item, game crshes and gives an error on line 793 of your script. Without the Battle Order works fine. I found this a little strange. Can you take a look at it? I know this is just a test script so no worries if you can't :)

 

EDIT: I messed around with the scripts and it looks like it was the problem. I tried your script with Yanfly battle engine and worked fine. I tried with it + the Battle Order and crashed.

Edited by ricardo.jl.simoes

Share this post


Link to post
Share on other sites

so ive been looking for a weight system and really it comes to this or xs.  xs was an issue because it only worked for items added through a specific cal which does not work well with my abs. anyways your script is nice and def could go a step further. like you said the weight causing issues for player like slower movement and what not. the thing i would like to do and i would think i could do with your current version, if i knew more about scripting, is have max weight be defined by differnt variables of users choosing.

 

for exampls xs had 1 setting for level ranges allowing some weight limits. another and most common option is max weight being determined by strength.

 

so i see this line in your script

 

Weight_Limit = 2000000

 

i did a little bit of java back in day but wouldn't it be easy to have the ability to set weight_limit to an equation that takes strength (atk) and lets say multiply it by some number like 100? simulating fallout type weight. just a thought. if you could even tell me how to set that line up to be able to do that, that would work too.

Share this post


Link to post
Share on other sites

Hi, is there anyway to make the max limit or weight to an in-game variable so that it can increase in game?

 

Well, i had the same question as well and someone else also had this question in mind. Ive been playing with this script to get the max weight to change in game but had no luck so i played around with the script and changed all the weight_limits and set it to variable 79 and it seemed to work. Im not a scripter so i dont know if i did that properly and my computer did not blow up yet d_d nor my character in game's head sooo, here's the script below. I'll keep running it and see if i run into any problems or if my computer blows up for the change i made >_>  

 

after copying and pasting this to the script editor, you can change the max weight which i put variable 79. So variable 79 is what you will have to use for a test run. If your computer blows up dont go pointing hands at me =D  Test at your own risk XD

 

 

 

=begin
#==============================================================================
 ** FP Inventory Plus
 Author: Tsukihime
 Date: Jul 10, 2012
------------------------------------------------------------------------------
 ** Change log
 Jul 10
   -fixed logic error where == wasn't returning false if no branches return
 Jul 9
   -restructured Game_Weapon, Game_Armor, and Game_Item to include a new
    BaseItem module
   -overwrote == logic to distinguish between RPG objects and custom objects.
 Jun 26
   -added proper item losing
 May 30
   -fixed issue where item type check wasn't checked properly
    eg: default weapon check assumes class == RPG::Weapon
 May 29
   -added counting options: count-by-item, count-by-stack
 May 27
   -added options to enable/disable item/weight limits
   -added item limit window
 May 26
   -added the imported boolean
 May 24
   -Initialized RPG classes
 May 22
   -Added "clear inventory" method to clear everything out
   -Clears out equips as well
 May 15, 2012
   - fixed some bugs
 May 14, 2012
   - Initial release
------------------------------------------------------------------------------    
 This script extends the default inventory system and all item-handling
 throughout the engine. All items will be fetched from the inventory, and
 instances of the specific item is stored and retrieved.
 
 You can specify the stack sizes for each item as well as their weights.
 You can specify item limits and weight limits for each item.
 All equips are treated independently.
 
 This script will act as the basis for all future item-related scripts.
 
 To specify an item/equip stack size, tag it with
 
    <stack: n>
 where n is an integer >= 1
    
 To specify the weight of an item/equip, tag it with
 
    <weight: n>
 where n is a real number
    
 To specify the the limit for an item/equip, tag it with
    <limit: n>
 where n is an integer >= 0
 
#==============================================================================
=end
$imported = {} if $imported.nil?
$imported["FP_InventoryPlus"] = true
#==============================================================================
# ** Configuration
#==============================================================================
module Feature_Plus
  module Inventory_System
    
    Use_Item_Limit = false
    Use_Weight_Limit = true
    
    # Item counting method. If "Count_Items" is true, then
    # Count_Stacks is not used
    
    Count_By_Stack = false # treat each stack as a single item
    Count_By_Item = true  # count every item individually
    
    # Stack defaults
    Default_Item_Stack = 99
    Default_Equip_Stack = 1
    
    # weight defaults
    Default_KeyItem_Weight = 0
    Default_Item_Weight = 1
    Default_Equip_Weight = 10
    
    Weight_Unit = "WT"
    
    # [current weight] / [max weight] [weight unit]
    Weight_Display = "%.2f/%s %s" 
    
    # [item_count] / [item_limit]
    Item_Display = "Items: %s/%s"
    
    # Inventory limit defaults
    Inventory_Limit = 10000    #max inventory size
    #regex
    Item_Limit = /<limit:?\s*(\d+)>/i      #max number of this item 
    Item_Weight = /<weight:?\s*(.*)>/i   #weight of this item
    Stack_Size = /<stack:?\s*(\d+)>/i     #stack size of this item
  end
end

#==============================================================================
# ** Rest of the script
#==============================================================================

module RPG
  class Item < UsableItem
    include Feature_Plus::Inventory_System
       
    def item_weight
      return @item_weight unless @item_weight.nil?
      res = Item_Weight.match(self.note)
      return @item_weight = res ? res[1].to_f : (key_item? ? Default_KeyItem_Weight : Default_Item_Weight)
    end
    
    def item_stack
      return @item_stack unless @item_stack.nil?
      res = Stack_Size.match(self.note)
      return @item_stack = res ? res[1].to_i : Default_Item_Stack
    end
    
    def item_limit
      return @item_limit unless @item_limit.nil?
      res = Item_Limit.match(self.note)
      return @item_limit = res ? res[1].to_i : Inventory_Limit
    end
  end

  class EquipItem < BaseItem
    include Feature_Plus::Inventory_System

    def item_weight
      return @item_weight unless @item_weight.nil?
      res = Item_Weight.match(self.note)
      return @item_weight = res ? res[1].to_f : Default_Equip_Weight
    end
    
    def item_stack
      return @item_stack unless @item_stack.nil?
      res = Stack_Size.match(self.note)
      return @item_stack = res ? res[1].to_i : Default_Equip_Stack
    end
    
    def item_limit
      return @item_limit unless @item_limit.nil?
      res = Item_Limit.match(self.note)
      return @item_limit = res ? res[1].to_i : Inventory_Limit
    end
  end
end

# this module is included by Game_Item, Game_Weapon, and Game_Armor
module BaseItem
  attr_reader :index          # index of item in the inventory slot
  attr_reader :count          # number of items in this stack
  attr_reader :class          #
  attr_reader :item_stack     # max items per stack
  attr_reader :item_weight    # weight per instance of item
  attr_reader :item_limit     # max number of items allowed to carry
  attr_reader :id             # database ID used to reference the type of item
  def initialize(item, index)
    super()
    init_base_attributes(item)
    @count = 0
    @index = index
    @id = item.id
    @item_stack = item.item_stack
    @item_weight = item.item_weight
    @item_limit = item.item_limit
    setup(item, index) if needs_setup?(item)
  end
  
  def setup(item, index)
  end
  
  def init_base_attributes(item)
    item.instance_variables.each do |attr|
      self.instance_variable_set(attr, item.instance_variable_get(attr))
    end
  end
  
  def amount_can_add?
    @item_stack - @count
  end
  
  def add_amount(amt)
    @count = [@count + amt, @item_stack].min
  end
  
  def lose_amount(amt)
    lost = [amt, @count].min
    @count = [@count - amt, 0].max
    return lost
  end
  
  def full?
    @count >= @item_stack
  end
  
  def can_add?
    return false if full?
    return true
  end
  
  def inspect
    "<%s>" % @name
  end
end

# This module is included in Game_Weapon and Game_Armor. It contains common
# methods shared by all equip items
module EquipItem

  def setup(item, index)
    # call anything from BaseItem
    super
  end
end

#==============================================================================
# ** Game_Item
#------------------------------------------------------------------------------
# This is an extension of RPG::Item. All of the methods defined in
# RPG::Item are inherited. When an item is created, it is wrapped by
# this Game_Item and all of the attributes are cloned
#==============================================================================

class Game_Item < RPG::Item
  include BaseItem  
  
  def setup(item, index)
    @class = Game_Item
  end
  
  def needs_setup?(item)
    item.class == RPG::Item
  end
  
  def ==(item)
    if item.class == RPG::Item
      return $data_items[@id] == item
    elsif item.is_a?(Game_Item)
      return self.equal?(item)
    end
    return false
  end
end

#==============================================================================
# ** Game_Weapon
#------------------------------------------------------------------------------
# This is an extension of RPG::Weapon. All of the methods defined in
# RPG::Weapon are inherited. When an item is created, it is wrapped by
# this Game_Weapon and all of the attributes are cloned
#==============================================================================

class Game_Weapon < RPG::Weapon
  include BaseItem
  include EquipItem
  
  alias :th_inventory_setup :setup
  def setup(item, index)
    @class = Game_Weapon
    @params = item.params.clone #we must clone this
    @name = item.name
    th_inventory_setup(item, index)
  end
  
  def needs_setup?(item)
    item.class == RPG::Weapon
  end
  
  def ==(item)
    if item.class == RPG::Weapon
      return $data_weapons[@id] == item
    elsif item.is_a?(Game_Weapon)
      return equal?(item)
    end
    return false
  end
end

#==============================================================================
# ** Game_Armor
#------------------------------------------------------------------------------
# This is an extension of RPG::Armor. All of the methods defined in
# RPG::Armor are inherited. When an item is created, it is wrapped by
# this Game_Armor and all of the attributes are cloned
#==============================================================================

class Game_Armor < RPG::Armor
  include BaseItem
  include EquipItem

  def setup(item, index)
    @class = Game_Armor
    @params = item.params.clone #we must clone this
    @name = item.name
  end
  
  def needs_setup?(item)
    item.class == RPG::Armor
  end
  
  def ==(item)
    if item.class == RPG::Armor
      return $data_armors[@id] == item
    elsif item.is_a?(RPG::Armor)
      return self.equal?(item)
    end
    return false
  end
end

#==============================================================================
# ** Game_Inventory
#------------------------------------------------------------------------------
# This is an inventory object. It represents a generic inventory, containing
# a set of items including common items, weapons, armors, and key items.
#
# All inventory related methods are defined and any access to the inventory
# should use the provided methods
#==============================================================================
class Game_Inventory
  include Feature_Plus::Inventory_System
  
  attr_reader :weight
  attr_reader :item_count
  def initialize
    @id = 0
    @name = ""
    @weight = 0
    @item_count = 0
    @items = {}
    @weapons = {}
    @armors = {}
    @discards = {}
    @inventory_limit = Inventory_Limit
    $game_variables[79]
  end
  
  def max_items
    @inventory_limit
  end
  
  def max_weight
    $game_variables[79]
  end
  
  def weight_exceeded?(item)
    return false unless Feature_Plus::Inventory_System::Use_Weight_Limit
    @weight + item.item_weight > $game_variables[79]
  end
  
  def items_exceeded?
    return false unless Feature_Plus::Inventory_System::Use_Item_Limit
    @item_count >= @inventory_limit
  end
  
  def limit_reached?(item)
    items_exceeded? || weight_exceeded?(item)
  end
  
  def can_add_amount?(item)
    
    if item.item_weight > 0
      return [[max_items - @item_count, (max_weight - @weight) / item.item_weight].min, 0].max
    end
    return [max_items - @item_count, 0].max
  end
    
  def get_item_type(item)
    return @items if item.is_a?(RPG::Item)
    return @weapons if item.is_a?(RPG::Weapon)
    return @armors  if item.is_a?(RPG::Armor)
    return nil
  end
  
  def is_system_item?(item)
    return [RPG::Weapon, RPG::Armor, RPG::Item].include?(item.class)
  end
  
  def item_number(item)
    container = get_item_type(item)
    return 0 unless container && container[item.id]
    return container[item.id].count unless item.instance_variable_defined?(:@index)
    return container[item.id][item.index].nil? ? 0 : container[item.id][item.index].count
  end
  
  def has_item?(item, include_equip=false)
    item_number(item) > 0
  end
    
  def gain_item(item, amount)
    container = get_item_type(item)
    return unless container
    valid_amount = [can_add_amount?(item), amount].min
    discard_amount = amount - valid_amount
    unless limit_reached?(item)
      container[item.id] = Game_InventorySlot.new(item) unless container[item.id]
      amount_avail = [container[item.id].can_add_amount?(item), valid_amount].min
      container[item.id].gain_item(item, amount_avail)
      update_inventory(container, item, amount_avail)
    end
    update_discards(item, discard_amount)
  end
  
  def lose_item(item, amount)
    container = get_item_type(item)
    return unless container
    return unless container[item.id]
    lost = container[item.id].lose_item(item, amount)
    update_inventory(container, item, -lost)
  end
  
  def update_inventory(container, item, added)
    @weight += item.item_weight * added
    @item_count += added
  end
  
  def update_discards(item, remains)
    return unless remains > 0
    p "Discarded %d %s" %[remains, item.name]
  end
  
  def clear_inventory(include_equips=false)
    $game_party.all_members.each {|actor| actor.clear_equips} if include_equips
    @weapons.clear
    @armors.clear
    @items.clear
    @item_count = 0
    @weight = 0
  end
  
  #--------------------------------------------------------------------------
  # * Accessor methods. Returns the same things that Game_Party used
  # to return
  #--------------------------------------------------------------------------
#~   
  def get_weapon(item_id)
    slot = @weapons[item_id]
    return unless slot
    return slot.stacks[0]
  end
  
  def get_armor(item_id)
    slot = @armors[item_id]
    return unless slot
    return slot.stacks[0]
  end
  
  def items
    @items.keys.sort.collect {|id| @items[id].stacks}.flatten
  end
  
  def weapons
    @weapons.keys.sort.collect {|id| @weapons[id].stacks}.flatten
  end
  
  def armors
    @armors.keys.sort.collect {|id| @armors[id].stacks}.flatten
  end
  
  def equip_items
    weapons.concat(armors)
  end
  
  def discards
    @discards
  end

  def all_items
    items.concat(weapons).concat(armors)
  end
end

#==============================================================================
# ** Game_InventorySlot
#------------------------------------------------------------------------------
# This is an inventory slot object. It provides information about this slot
# such as the number of items and total weight. It stores an instance of
# my custom game item in an array
#==============================================================================

class Game_InventorySlot
  include Feature_Plus::Inventory_System
  
  attr_reader :item_stack
  attr_reader :count
  attr_reader :weight
  def initialize(item)
    @id = item.id
    @item = item
    @stacks = []                     # individual instances of this item
    @item_weight = item.item_weight
    @count = 0                       # number of items across all stacks
    @weight = 0                      # weight of items across all stacks
    @item_stack = item.item_stack    # number of items per stack
    @item_limit = item.item_limit
  end
  
  def [](index)
    return unless @stacks[index]
    @stacks[index]
  end
  
  def max_items
    @item_limit
  end
  
  def max_weight
    $game_variables[79]
  end
  
  def stack_size
    @item_stack
  end
  
  #--------------------------------------------------------------------------
  # * Return all non-nil stacks
  #--------------------------------------------------------------------------
  def stacks
    @stacks.select {|stack| !stack.nil?}
  end
  
  def slot_exceeded?
    @count >= max_items
  end

  def weight_exceeded?(item)
    return false unless Feature_Plus::Inventory_System::Use_Weight_Limit
    @weight >= max_weight
  end
  
  def can_add?(item)
    return false if slot_exceeded? || weight_exceeded?(item)
    return true
  end
  
  def can_add_amount?(item)
    if item.item_weight > 0
      return [[max_items - @count, (max_weight - @weight) / item.item_weight].min, 0].max
    end
    return [max_items - @count, 0].max
  end
  
  # gets the first available stack to add item to
  def get_stack(item)
    (0 .. @stacks.size ).find { |k| @stacks[k].nil? || @stacks[k].can_add?}
  end
  
  # gets the first non-nil stack
  def first_stack
    (0 .. @stacks.size ).find { |k| @stacks[k]}
  end
  
  def make_item(item, i)
    @stacks[i] = Game_Item.new(item, i) if item.is_a?(RPG::Item)
    @stacks[i] = Game_Weapon.new(item, i) if item.is_a?(RPG::Weapon)
    @stacks[i] = Game_Armor.new(item, i) if item.is_a?(RPG::Armor)
  end
  
  def gain_item(item, amount)
    return unless can_add?(item)
    total = amount
    while amount > 0
      i = get_stack(item)
      make_item(item, i) if @stacks[i].nil?
      stack = @stacks[i]
      amt = stack.amount_can_add?
      @stacks[i].add_amount([amount, amount - amt, 0].max)
      amount -= amt
    end
    update_slot(item, total)
  end
  
  def delete_stack(index)
    @stacks.delete_at(index) 
    @stacks.insert(index, nil)
  end
  
  def lose_item(item, amount)
    total_lost = 0
    while @count > 0 && amount > 0
      i = item.index rescue first_stack
      if i
        i = first_stack if @stacks[i].count == 0
        stack = @stacks[i]
        lost_amount = stack.lose_amount(amount)
        delete_stack(i) if @stacks[i].count == 0
        update_slot(item, -lost_amount)
        total_lost += lost_amount
        amount -= lost_amount
      end
    end
    return total_lost
  end
  
  def update_slot(item, amount)
    @count += amount
    @weight += item.item_weight * amount 
  end
end

class Game_Actor < Game_Battler
  
  alias fp_inventory_actor_initialize initialize
  def initialize(actor_id)
    fp_inventory_actor_initialize(actor_id)
    @last_skill = Game_CustItem.new
  end
  
  def clear_equips
    @equips = Array.new(equip_slots.size) { Game_CustItem.new }
  end

  #need to set up initial equips properly
  def init_equips(equips)
    @equips = Array.new(equip_slots.size) { Game_CustItem.new }
    equips.each_with_index do |item_id, i|
      etype_id = index_to_etype_id(i)
      slot_id = empty_slot(etype_id)
      if item_id > 0
        @equips[slot_id].object = get_initial_equip(etype_id == 0, item_id) if slot_id
      else
        @equips[slot_id].object = nil if slot_id
      end
    end
    refresh
  end
  
  def get_initial_equip(is_weapon, item_id)
    if is_weapon
      return Game_Weapon.new($data_weapons[item_id], 0)
    else
      return Game_Armor.new($data_armors[item_id], 0)
    end
  end
  
  def xequips
    @equips.collect {|item| item.object }
  end
  
  def armors
    @equips.select {|item| item.is_armor? }.collect {|item| item.object }
  end
  
  def change_equip(slot_id, item)
    return unless trade_item_with_party(item, equips[slot_id])
    return if item && equip_slots[slot_id] != item.etype_id
    @equips[slot_id].object = item
    refresh
  end
  
  # event command "change equipment"
  def change_equip_by_id(slot_id, item_id)
    if equip_slots[slot_id] == 0
      item = $game_party.get_weapon(item_id)
      return unless item
      change_equip(slot_id, item)
    else
      index = $game_party.get_armor(item_id)
      return unless item
      change_equip(slot_id, Game_Armor.new($data_armors[item_id], index))
    end
  end
end

#==============================================================================
# ** Game_party
#------------------------------------------------------------------------------
# All inventory access methods are re-written to allow the Inventory object
# to properly handle those requests
#==============================================================================

class Game_Party < Game_Unit

  attr_reader :inventory
  alias tsuki_inventory_party_initialize initialize
  def initialize
    tsuki_inventory_party_initialize
    @inventory = Game_Inventory.new
    @last_item = Game_CustItem.new
  end
  
  def clear_inventory(include_equip=false)
    @inventory.clear_inventory(include_equip)
  end
  
  def weight
    @inventory.weight
  end
  
  def items
    @inventory.items
  end
  
  def weapons
    @inventory.weapons
  end 
  
  def armors
    @inventory.armors
  end
  
  def equip_items
    @inventory.equip_items
  end
  
  def all_items
    @inventory.all_items
  end
  
  def item_number(item)
    @inventory.item_number(item)
  end
  
  def has_item?(item, include_equip=false)
    @inventory.has_item?(item)
  end
    
  def gain_item(item, amount, include_equip = false)
    if amount < 0
      lose_item(item, -amount, include_equip)
    else
      @inventory.gain_item(item, amount)
    end
  end
  
  def lose_item(item, amount, include_equip = false)
    @inventory.lose_item(item, amount)
  end
  
  def max_item_number(item)
    99
  end
  
  def max_weight
    @inventory.max_weight
  end
  
  def item_count
    @inventory.item_count
  end
  
  def max_items
    @inventory.max_items
  end
  
  def item_max?(item)
    item_number(item) >= max_item_number(item)
  end
  
  def get_weapon(item_id)
    @inventory.get_weapon(item_id)
  end
  
  def get_armor(item_id)
    @inventory.get_armor(item_id)
  end
end

#==============================================================================
# ** Game_CustItem
#------------------------------------------------------------------------------
# This is a variation of Game_BaseItem that stores the actual instance of
# the object rather than storing references to the database
#==============================================================================

class Game_CustItem < Game_BaseItem
  def initialize
    super
    @object = nil
  end
  
  def is_skill?;   @object.is_a?(RPG::Skill);   end
  def is_item?;    @object.is_a?(RPG::Item);    end
  def is_weapon?;  @object.is_a?(RPG::Weapon);  end
  def is_armor?;   @object.is_a?(RPG::Armor);   end
  
  def object
    return nil unless @object
    return @object 
  end
  
  def object=(item)
    @class = item.class
    @item_id = item.id if item
    @object = item
  end
  
  def set_equip(is_weapon, item_id)
    @class = is_weapon ? RPG::Weapon : RPG::Armor
    @item_id = item_id
    @object = is_weapon ? $data_weapons[item_id] : $data_armors[item_id]
  end
end

class Game_Action

  alias fp_initialize_clear_action clear
  def clear
    fp_initialize_clear_action
    @item = Game_CustItem.new
  end
  
  def set_item(item)
    @item.object = item
    self
  end
end

#==============================================================================
# ** Scenes
#==============================================================================

class Scene_Battle < Scene_Base
  
  def on_item_ok
    @item = @item_window.item
    BattleManager.actor.input.set_item(@item)
    if !@item.need_selection?
      @item_window.hide
      next_command
    elsif @item.for_opponent?
      select_enemy_selection
    else
      select_actor_selection
    end
    $game_party.last_item.object = @item
  end
end

class Scene_Menu < Scene_MenuBase
  
  alias fp_inventory_menu_start start
  def start
    fp_inventory_menu_start
    create_limit_windows
  end
    
  def create_limit_windows
    y = 360
    if Feature_Plus::Inventory_System::Use_Weight_Limit
      @weight_window = Window_Weight.new(385, Graphics.height - y - @gold_window.height)
      y += 48
    end
    if Feature_Plus::Inventory_System::Use_Item_Limit
      @item_limit_window = Window_ItemLimit.new(0, Graphics.height - y - @gold_window.height)
    end
  end
end

class Scene_Item < Scene_ItemBase
  
  alias fp_inventory_item_start start
  def start
    fp_inventory_item_start
    create_limit_windows
  end
  
  def create_limit_windows
    x = 160
    if Feature_Plus::Inventory_System::Use_Weight_Limit
      @weight_window = Window_Weight.new(Graphics.width - x, 0)
      @weight_window.z = 200
      @actor_window.z = 300
      x += 160
    end
    if Feature_Plus::Inventory_System::Use_Item_Limit
      @item_limit_window = Window_ItemLimit.new(Graphics.width - x, 0)
      @item_limit_window.z = 200
      x += 160
    end
  end
  
  alias fp_inventory_use_item use_item
  def use_item
    fp_inventory_use_item
    @weight_window.refresh if Feature_Plus::Inventory_System::Use_Weight_Limit
    @item_limit_window.refresh if  Feature_Plus::Inventory_System::Use_Item_Limit
  end
end

class Window_ItemLimit < Window_Base
  include Feature_Plus::Inventory_System

  def initialize(x, y)
    super(x, y, window_width, fitting_height(1))
    refresh
  end
  
  def window_width
    160
  end

  def refresh
    contents.clear
    draw_weight_value(4, 0)
  end
  
  def draw_weight_value(x, y)
    text = sprintf(Item_Display, item_count, item_limit)
    change_color(normal_color)    
    draw_text(x, y, self.contents.width - 4, line_height, text, 1)
  end
  
  def item_limit
    $game_party.max_items
  end
  #--------------------------------------------------------------------------
  # * Get inventory weight
  #--------------------------------------------------------------------------
  def item_count
    $game_party.item_count
  end
  #--------------------------------------------------------------------------
  # * Open Window
  #--------------------------------------------------------------------------
  def open
    refresh
    super
  end
end

class Window_Weight < Window_Base
  include Feature_Plus::Inventory_System
#--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(x, y)
    super(x, y, window_width, fitting_height(1))
    refresh
  end
  #--------------------------------------------------------------------------
  # * Get Window Width
  #--------------------------------------------------------------------------
  def window_width
    return 160
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    draw_weight_value(4, 0, contents.width - 8)
  end
  
  def draw_weight_value(x, y, width)
    text = sprintf(Weight_Display, weight, max_weight, weight_unit)
    change_color(normal_color)    
    draw_text(x, y, width, line_height, text, 2)
  end
  
  def weight_unit
    Weight_Unit
  end
  
  def max_weight
    $game_party.max_weight
  end
  #--------------------------------------------------------------------------
  # * Get inventory weight
  #--------------------------------------------------------------------------
  def weight
    $game_party.weight
  end
  #--------------------------------------------------------------------------
  # * Open Window
  #--------------------------------------------------------------------------
  def open
    refresh
    super
  end
end

class Game_Interpreter
  def can_add_amount?(item)
    return false if item.nil?
    item = $data_items[item] unless item.is_a?(RPG::BaseItem)
    return $game_party.inventory.can_add_amount?(item)
  end
  
  def armor(i)
    return $data_armors[i]
  end

  def weapon(i)
    return $data_weapons[i]
  end
  
  def item(i)
    return @data_items[i]
  end
end 

 

 

 

EDITED:

I played around with the script some more and made more edition but like i said, i am no scripter and things can blow up if u miss test it!  So, this script below consist of the top script and also allows to pass the max limit in inventory which leads to allowing the slow movement when you pass the max limit. How can this be done??

 

Set an event in parallel process and have a conditional branch that checks this $game_party.overweight? == true

If it returns true then you can put a state to change players speed or just change the players speed to whatever you want and put something if false like put the normal speed back.

 

Thanks to Esrann for coming up with the idea

If true,

> add conditon "Encumbered"

> set move route: [slow player speed]

 

Else,

 If condition "Encumbered" == true

  > remove condition "Encumbered"

  > set move route: [normal player speed]

 

You can set up the "Encubered" state to give whatever debuffs you want.

This is the way I use it, there could be more elegant way to make it 100% script.

 

Hope this helps!

 

Here is my new edited version. Like i said, i am no scripter and things can go horribly wrong when pluggin this baby in so take it at your own shot!  :D

 

 

=begin
#==============================================================================
 ** FP Inventory Plus
 Author: Tsukihime
 Date: Jul 10, 2012
------------------------------------------------------------------------------
 ** Change log
 Jul 10
   -fixed logic error where == wasn't returning false if no branches return
 Jul 9
   -restructured Game_Weapon, Game_Armor, and Game_Item to include a new
    BaseItem module
   -overwrote == logic to distinguish between RPG objects and custom objects.
 Jun 26
   -added proper item losing
 May 30
   -fixed issue where item type check wasn't checked properly
    eg: default weapon check assumes class == RPG::Weapon
 May 29
   -added counting options: count-by-item, count-by-stack
 May 27
   -added options to enable/disable item/weight limits
   -added item limit window
 May 26
   -added the imported boolean
 May 24
   -Initialized RPG classes
 May 22
   -Added "clear inventory" method to clear everything out
   -Clears out equips as well
 May 15, 2012
   - fixed some bugs
 May 14, 2012
   - Initial release
------------------------------------------------------------------------------    
 This script extends the default inventory system and all item-handling
 throughout the engine. All items will be fetched from the inventory, and
 instances of the specific item is stored and retrieved.
 
 You can specify the stack sizes for each item as well as their weights.
 You can specify item limits and weight limits for each item.
 All equips are treated independently.
 
 This script will act as the basis for all future item-related scripts.
 
 To specify an item/equip stack size, tag it with
 
    <stack: n>
 where n is an integer >= 1
    
 To specify the weight of an item/equip, tag it with
 
    <weight: n>
 where n is a real number
    
 To specify the the limit for an item/equip, tag it with
    <limit: n>
 where n is an integer >= 0
 
#==============================================================================
=end
$imported = {} if $imported.nil?
$imported["FP_InventoryPlus"] = true
#==============================================================================
# ** Configuration
#==============================================================================
module Feature_Plus
  module Inventory_System
    
    Use_Item_Limit = false
    Use_Weight_Limit = true
    
    # Item counting method. If "Count_Items" is true, then
    # Count_Stacks is not used
    
    Count_By_Stack = false # treat each stack as a single item
    Count_By_Item = true  # count every item individually
    
    # Stack defaults
    Default_Item_Stack = 99
    Default_Equip_Stack = 1
    
    # weight defaults
    Default_KeyItem_Weight = 0
    Default_Item_Weight = 1
    Default_Equip_Weight = 10
    
    Weight_Unit = "WT"
    
    # [current weight] / [max weight] [weight unit]
    Weight_Display = "%.2f/%s %s" 
    
    # [item_count] / [item_limit]
    Item_Display = "Items: %s/%s"
    
    # Inventory limit defaults
    Inventory_Limit = 10000    #max inventory size
    #regex
    Item_Limit = /<limit:?\s*(\d+)>/i      #max number of this item 
    Item_Weight = /<weight:?\s*(.*)>/i   #weight of this item
    Stack_Size = /<stack:?\s*(\d+)>/i     #stack size of this item
  end
end

#==============================================================================
# ** Rest of the script
#==============================================================================

module RPG
  class Item < UsableItem
    include Feature_Plus::Inventory_System
       
    def item_weight
      return @item_weight unless @item_weight.nil?
      res = Item_Weight.match(self.note)
      return @item_weight = res ? res[1].to_f : (key_item? ? Default_KeyItem_Weight : Default_Item_Weight)
    end
    
    def item_stack
      return @item_stack unless @item_stack.nil?
      res = Stack_Size.match(self.note)
      return @item_stack = res ? res[1].to_i : Default_Item_Stack
    end
    
    def item_limit
      return @item_limit unless @item_limit.nil?
      res = Item_Limit.match(self.note)
      return @item_limit = res ? res[1].to_i : Inventory_Limit
    end
  end

  class EquipItem < BaseItem
    include Feature_Plus::Inventory_System

    def item_weight
      return @item_weight unless @item_weight.nil?
      res = Item_Weight.match(self.note)
      return @item_weight = res ? res[1].to_f : Default_Equip_Weight
    end
    
    def item_stack
      return @item_stack unless @item_stack.nil?
      res = Stack_Size.match(self.note)
      return @item_stack = res ? res[1].to_i : Default_Equip_Stack
    end
    
    def item_limit
      return @item_limit unless @item_limit.nil?
      res = Item_Limit.match(self.note)
      return @item_limit = res ? res[1].to_i : Inventory_Limit
    end
  end
end

# this module is included by Game_Item, Game_Weapon, and Game_Armor
module BaseItem
  attr_reader :index          # index of item in the inventory slot
  attr_reader :count          # number of items in this stack
  attr_reader :class          #
  attr_reader :item_stack     # max items per stack
  attr_reader :item_weight    # weight per instance of item
  attr_reader :item_limit     # max number of items allowed to carry
  attr_reader :id             # database ID used to reference the type of item
  def initialize(item, index)
    super()
    init_base_attributes(item)
    @count = 0
    @index = index
    @id = item.id
    @item_stack = item.item_stack
    @item_weight = item.item_weight
    @item_limit = item.item_limit
    setup(item, index) if needs_setup?(item)
  end
  
  def setup(item, index)
  end
  
  def init_base_attributes(item)
    item.instance_variables.each do |attr|
      self.instance_variable_set(attr, item.instance_variable_get(attr))
    end
  end
  
  def amount_can_add?
    @item_stack - @count
  end
  
  def add_amount(amt)
    @count = [@count + amt, @item_stack].min
  end
  
  def lose_amount(amt)
    lost = [amt, @count].min
    @count = [@count - amt, 0].max
    return lost
  end
  
  def full?
    @count >= @item_stack
  end
  
  def can_add?
    return false if full?
    return true
  end
  
  def inspect
    "<%s>" % @name
  end
end

# This module is included in Game_Weapon and Game_Armor. It contains common
# methods shared by all equip items
module EquipItem

  def setup(item, index)
    # call anything from BaseItem
    super
  end
end

#==============================================================================
# ** Game_Item
#------------------------------------------------------------------------------
# This is an extension of RPG::Item. All of the methods defined in
# RPG::Item are inherited. When an item is created, it is wrapped by
# this Game_Item and all of the attributes are cloned
#==============================================================================

class Game_Item < RPG::Item
  include BaseItem  
  
  def setup(item, index)
    @class = Game_Item
  end
  
  def needs_setup?(item)
    item.class == RPG::Item
  end
  
  def ==(item)
    if item.class == RPG::Item
      return $data_items[@id] == item
    elsif item.is_a?(Game_Item)
      return self.equal?(item)
    end
    return false
  end
end

#==============================================================================
# ** Game_Weapon
#------------------------------------------------------------------------------
# This is an extension of RPG::Weapon. All of the methods defined in
# RPG::Weapon are inherited. When an item is created, it is wrapped by
# this Game_Weapon and all of the attributes are cloned
#==============================================================================

class Game_Weapon < RPG::Weapon
  include BaseItem
  include EquipItem
  
  alias :th_inventory_setup :setup
  def setup(item, index)
    @class = Game_Weapon
    @params = item.params.clone #we must clone this
    @name = item.name
    th_inventory_setup(item, index)
  end
  
  def needs_setup?(item)
    item.class == RPG::Weapon
  end
  
  def ==(item)
    if item.class == RPG::Weapon
      return $data_weapons[@id] == item
    elsif item.is_a?(Game_Weapon)
      return equal?(item)
    end
    return false
  end
end

#==============================================================================
# ** Game_Armor
#------------------------------------------------------------------------------
# This is an extension of RPG::Armor. All of the methods defined in
# RPG::Armor are inherited. When an item is created, it is wrapped by
# this Game_Armor and all of the attributes are cloned
#==============================================================================

class Game_Armor < RPG::Armor
  include BaseItem
  include EquipItem

  def setup(item, index)
    @class = Game_Armor
    @params = item.params.clone #we must clone this
    @name = item.name
  end
  
  def needs_setup?(item)
    item.class == RPG::Armor
  end
  
  def ==(item)
    if item.class == RPG::Armor
      return $data_armors[@id] == item
    elsif item.is_a?(RPG::Armor)
      return self.equal?(item)
    end
    return false
  end
end

#==============================================================================
# ** Game_Inventory
#------------------------------------------------------------------------------
# This is an inventory object. It represents a generic inventory, containing
# a set of items including common items, weapons, armors, and key items.
#
# All inventory related methods are defined and any access to the inventory
# should use the provided methods
#==============================================================================
class Game_Inventory
  include Feature_Plus::Inventory_System
  
  attr_reader :weight
  attr_reader :item_count
  def initialize
    @id = 0
    @name = ""
    @weight = 0
    @item_count = 0
    @items = {}
    @weapons = {}
    @armors = {}
    @discards = {}
    @inventory_limit = Inventory_Limit
    $game_variables[79]
  end
  
  def max_items
    @inventory_limit
  end
  
  def max_weight
    $game_variables[79]
  end
  
  
  def items_exceeded?
    return false unless Feature_Plus::Inventory_System::Use_Item_Limit
    @item_count >= @inventory_limit
  end
  
  def limit_reached?(item)
    items_exceeded?
  end
  
  def can_add_amount?(item)
    return [max_items - @item_count, 0].max
  end
    
  def get_item_type(item)
    return @items if item.is_a?(RPG::Item)
    return @weapons if item.is_a?(RPG::Weapon)
    return @armors  if item.is_a?(RPG::Armor)
    return nil
  end
  
  def is_system_item?(item)
    return [RPG::Weapon, RPG::Armor, RPG::Item].include?(item.class)
  end
  
  def item_number(item)
    container = get_item_type(item)
    return 0 unless container && container[item.id]
    return container[item.id].count unless item.instance_variable_defined?(:@index)
    return container[item.id][item.index].nil? ? 0 : container[item.id][item.index].count
  end
  
  def has_item?(item, include_equip=false)
    item_number(item) > 0
  end
    
  def gain_item(item, amount)
    container = get_item_type(item)
    return unless container
    valid_amount = [can_add_amount?(item), amount].min
    discard_amount = amount - valid_amount
    unless limit_reached?(item)
      container[item.id] = Game_InventorySlot.new(item) unless container[item.id]
      amount_avail = [container[item.id].can_add_amount?(item), valid_amount].min
      container[item.id].gain_item(item, amount_avail)
      update_inventory(container, item, amount_avail)
    end
    update_discards(item, discard_amount)
  end
  
  def lose_item(item, amount)
    container = get_item_type(item)
    return unless container
    return unless container[item.id]
    lost = container[item.id].lose_item(item, amount)
    update_inventory(container, item, -lost)
  end
  
  def update_inventory(container, item, added)
    @weight += item.item_weight * added
    @item_count += added
  end
  
  def update_discards(item, remains)
    return unless remains > 0
    p "Discarded %d %s" %[remains, item.name]
  end
  
  def clear_inventory(include_equips=false)
    $game_party.all_members.each {|actor| actor.clear_equips} if include_equips
    @weapons.clear
    @armors.clear
    @items.clear
    @item_count = 0
    @weight = 0
  end
  
  #--------------------------------------------------------------------------
  # * Accessor methods. Returns the same things that Game_Party used
  # to return
  #--------------------------------------------------------------------------
#~   
  def get_weapon(item_id)
    slot = @weapons[item_id]
    return unless slot
    return slot.stacks[0]
  end
  
  def get_armor(item_id)
    slot = @armors[item_id]
    return unless slot
    return slot.stacks[0]
  end
  
  def items
    @items.keys.sort.collect {|id| @items[id].stacks}.flatten
  end
  
  def weapons
    @weapons.keys.sort.collect {|id| @weapons[id].stacks}.flatten
  end
  
  def armors
    @armors.keys.sort.collect {|id| @armors[id].stacks}.flatten
  end
  
  def equip_items
    weapons.concat(armors)
  end
  
  def discards
    @discards
  end

  def all_items
    items.concat(weapons).concat(armors)
  end
end

#==============================================================================
# ** Game_InventorySlot
#------------------------------------------------------------------------------
# This is an inventory slot object. It provides information about this slot
# such as the number of items and total weight. It stores an instance of
# my custom game item in an array
#==============================================================================

class Game_InventorySlot
  include Feature_Plus::Inventory_System
  
  attr_reader :item_stack
  attr_reader :count
  attr_reader :weight
  def initialize(item)
    @id = item.id
    @item = item
    @stacks = []                     # individual instances of this item
    @item_weight = item.item_weight
    @count = 0                       # number of items across all stacks
    @weight = 0                      # weight of items across all stacks
    @item_stack = item.item_stack    # number of items per stack
    @item_limit = item.item_limit
  end
  
  def [](index)
    return unless @stacks[index]
    @stacks[index]
  end
  
  def max_items
    @item_limit
  end
  
  def max_weight
    $game_variables[79]
  end
  
  def stack_size
    @item_stack
  end
  
  #--------------------------------------------------------------------------
  # * Return all non-nil stacks
  #--------------------------------------------------------------------------
  def stacks
    @stacks.select {|stack| !stack.nil?}
  end
  
  def slot_exceeded?
    @count >= max_items
  end

  
  def can_add?(item)
    return false if slot_exceeded?
    return true
  end
  
  def can_add_amount?(item)
    return [max_items - @count, 0].max
  end
  
  # gets the first available stack to add item to
  def get_stack(item)
    (0 .. @stacks.size ).find { |k| @stacks[k].nil? || @stacks[k].can_add?}
  end
  
  # gets the first non-nil stack
  def first_stack
    (0 .. @stacks.size ).find { |k| @stacks[k]}
  end
  
  def make_item(item, i)
    @stacks[i] = Game_Item.new(item, i) if item.is_a?(RPG::Item)
    @stacks[i] = Game_Weapon.new(item, i) if item.is_a?(RPG::Weapon)
    @stacks[i] = Game_Armor.new(item, i) if item.is_a?(RPG::Armor)
  end
  
  def gain_item(item, amount)
    return unless can_add?(item)
    total = amount
    while amount > 0
      i = get_stack(item)
      make_item(item, i) if @stacks[i].nil?
      stack = @stacks[i]
      amt = stack.amount_can_add?
      @stacks[i].add_amount([amount, amount - amt, 0].max)
      amount -= amt
    end
    update_slot(item, total)
  end
  
  def delete_stack(index)
    @stacks.delete_at(index) 
    @stacks.insert(index, nil)
  end
  
  def lose_item(item, amount)
    total_lost = 0
    while @count > 0 && amount > 0
      i = item.index rescue first_stack
      if i
        i = first_stack if @stacks[i].count == 0
        stack = @stacks[i]
        lost_amount = stack.lose_amount(amount)
        delete_stack(i) if @stacks[i].count == 0
        update_slot(item, -lost_amount)
        total_lost += lost_amount
        amount -= lost_amount
      end
    end
    return total_lost
  end
  
  def update_slot(item, amount)
    @count += amount
    @weight += item.item_weight * amount 
  end
end

class Game_Actor < Game_Battler
  
  alias fp_inventory_actor_initialize initialize
  def initialize(actor_id)
    fp_inventory_actor_initialize(actor_id)
    @last_skill = Game_CustItem.new
  end
  
  def clear_equips
    @equips = Array.new(equip_slots.size) { Game_CustItem.new }
  end

  #need to set up initial equips properly
  def init_equips(equips)
    @equips = Array.new(equip_slots.size) { Game_CustItem.new }
    equips.each_with_index do |item_id, i|
      etype_id = index_to_etype_id(i)
      slot_id = empty_slot(etype_id)
      if item_id > 0
        @equips[slot_id].object = get_initial_equip(etype_id == 0, item_id) if slot_id
      else
        @equips[slot_id].object = nil if slot_id
      end
    end
    refresh
  end
  
  def get_initial_equip(is_weapon, item_id)
    if is_weapon
      return Game_Weapon.new($data_weapons[item_id], 0)
    else
      return Game_Armor.new($data_armors[item_id], 0)
    end
  end
  
  def xequips
    @equips.collect {|item| item.object }
  end
  
  def armors
    @equips.select {|item| item.is_armor? }.collect {|item| item.object }
  end
  
  def change_equip(slot_id, item)
    return unless trade_item_with_party(item, equips[slot_id])
    return if item && equip_slots[slot_id] != item.etype_id
    @equips[slot_id].object = item
    refresh
  end
  
  # event command "change equipment"
  def change_equip_by_id(slot_id, item_id)
    if equip_slots[slot_id] == 0
      item = $game_party.get_weapon(item_id)
      return unless item
      change_equip(slot_id, item)
    else
      index = $game_party.get_armor(item_id)
      return unless item
      change_equip(slot_id, Game_Armor.new($data_armors[item_id], index))
    end
  end
end

#==============================================================================
# ** Game_party
#------------------------------------------------------------------------------
# All inventory access methods are re-written to allow the Inventory object
# to properly handle those requests
#==============================================================================

class Game_Party < Game_Unit

  attr_reader :inventory
  alias tsuki_inventory_party_initialize initialize
  def initialize
    tsuki_inventory_party_initialize
    @inventory = Game_Inventory.new
    @last_item = Game_CustItem.new
  end
  
  def clear_inventory(include_equip=false)
    @inventory.clear_inventory(include_equip)
  end
  
  def weight
    @inventory.weight
  end
  
  def items
    @inventory.items
  end
  
  def weapons
    @inventory.weapons
  end 
  
  def armors
    @inventory.armors
  end
  
  def equip_items
    @inventory.equip_items
  end
  
  def all_items
    @inventory.all_items
  end
  
  def item_number(item)
    @inventory.item_number(item)
  end
  
  def has_item?(item, include_equip=false)
    @inventory.has_item?(item)
  end
    
  def gain_item(item, amount, include_equip = false)
    if amount < 0
      lose_item(item, -amount, include_equip)
    else
      @inventory.gain_item(item, amount)
    end
  end
  
  def lose_item(item, amount, include_equip = false)
    @inventory.lose_item(item, amount)
  end
  
  def max_item_number(item)
    99
  end
  
  def max_weight
    @inventory.max_weight
  end
  
  def item_count
    @inventory.item_count
  end
  
  def max_items
    @inventory.max_items
  end
  
  def item_max?(item)
    item_number(item) >= max_item_number(item)
  end
  
  def get_weapon(item_id)
    @inventory.get_weapon(item_id)
  end
  
  def get_armor(item_id)
    @inventory.get_armor(item_id)
  end
  
  def overweight?
  weight > max_weight
  end
end

#==============================================================================
# ** Game_CustItem
#------------------------------------------------------------------------------
# This is a variation of Game_BaseItem that stores the actual instance of
# the object rather than storing references to the database
#==============================================================================

class Game_CustItem < Game_BaseItem
  def initialize
    super
    @object = nil
  end
  
  def is_skill?;   @object.is_a?(RPG::Skill);   end
  def is_item?;    @object.is_a?(RPG::Item);    end
  def is_weapon?;  @object.is_a?(RPG::Weapon);  end
  def is_armor?;   @object.is_a?(RPG::Armor);   end
  
  def object
    return nil unless @object
    return @object 
  end
  
  def object=(item)
    @class = item.class
    @item_id = item.id if item
    @object = item
  end
  
  def set_equip(is_weapon, item_id)
    @class = is_weapon ? RPG::Weapon : RPG::Armor
    @item_id = item_id
    @object = is_weapon ? $data_weapons[item_id] : $data_armors[item_id]
  end
end

class Game_Action

  alias fp_initialize_clear_action clear
  def clear
    fp_initialize_clear_action
    @item = Game_CustItem.new
  end
  
  def set_item(item)
    @item.object = item
    self
  end
end

#==============================================================================
# ** Scenes
#==============================================================================

class Scene_Battle < Scene_Base
  
  def on_item_ok
    @item = @item_window.item
    BattleManager.actor.input.set_item(@item)
    if !@item.need_selection?
      @item_window.hide
      next_command
    elsif @item.for_opponent?
      select_enemy_selection
    else
      select_actor_selection
    end
    $game_party.last_item.object = @item
  end
end

class Scene_Menu < Scene_MenuBase
  
  alias fp_inventory_menu_start start
  def start
    fp_inventory_menu_start
    create_limit_windows
  end
    
  def create_limit_windows
    y = 360
    if Feature_Plus::Inventory_System::Use_Weight_Limit
      @weight_window = Window_Weight.new(385, Graphics.height - y - @gold_window.height)
      y += 48
    end
    if Feature_Plus::Inventory_System::Use_Item_Limit
      @item_limit_window = Window_ItemLimit.new(0, Graphics.height - y - @gold_window.height)
    end
  end
end

class Scene_Item < Scene_ItemBase
  
  alias fp_inventory_item_start start
  def start
    fp_inventory_item_start
    create_limit_windows
  end
  
  def create_limit_windows
    x = 160
    if Feature_Plus::Inventory_System::Use_Weight_Limit
      @weight_window = Window_Weight.new(Graphics.width - x, 0)
      @weight_window.z = 200
      @actor_window.z = 300
      x += 160
    end
    if Feature_Plus::Inventory_System::Use_Item_Limit
      @item_limit_window = Window_ItemLimit.new(Graphics.width - x, 0)
      @item_limit_window.z = 200
      x += 160
    end
  end
  
  alias fp_inventory_use_item use_item
  def use_item
    fp_inventory_use_item
    @weight_window.refresh if Feature_Plus::Inventory_System::Use_Weight_Limit
    @item_limit_window.refresh if  Feature_Plus::Inventory_System::Use_Item_Limit
  end
end

class Window_ItemLimit < Window_Base
  include Feature_Plus::Inventory_System

  def initialize(x, y)
    super(x, y, window_width, fitting_height(1))
    refresh
  end
  
  def window_width
    160
  end

  def refresh
    contents.clear
    draw_weight_value(4, 0)
  end
  
  def draw_weight_value(x, y)
    text = sprintf(Item_Display, item_count, item_limit)
    change_color(normal_color)    
    draw_text(x, y, self.contents.width - 4, line_height, text, 1)
  end
  
  def item_limit
    $game_party.max_items
  end
  #--------------------------------------------------------------------------
  # * Get inventory weight
  #--------------------------------------------------------------------------
  def item_count
    $game_party.item_count
  end
  #--------------------------------------------------------------------------
  # * Open Window
  #--------------------------------------------------------------------------
  def open
    refresh
    super
  end
end

class Window_Weight < Window_Base
  include Feature_Plus::Inventory_System
#--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(x, y)
    super(x, y, window_width, fitting_height(1))
    refresh
  end
  #--------------------------------------------------------------------------
  # * Get Window Width
  #--------------------------------------------------------------------------
  def window_width
    return 160
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    draw_weight_value(4, 0, contents.width - 8)
  end
  
  def draw_weight_value(x, y, width)
    text = sprintf(Weight_Display, weight, max_weight, weight_unit)
    change_color(normal_color)    
    draw_text(x, y, width, line_height, text, 2)
  end
  
  def weight_unit
    Weight_Unit
  end
  
  def max_weight
    $game_party.max_weight
  end
  #--------------------------------------------------------------------------
  # * Get inventory weight
  #--------------------------------------------------------------------------
  def weight
    $game_party.weight
  end
  #--------------------------------------------------------------------------
  # * Open Window
  #--------------------------------------------------------------------------
  def open
    refresh
    super
  end
end

class Game_Interpreter
  def can_add_amount?(item)
    return false if item.nil?
    item = $data_items[item] unless item.is_a?(RPG::BaseItem)
    return $game_party.inventory.can_add_amount?(item)
  end
  
  def armor(i)
    return $data_armors[i]
  end

  def weapon(i)
    return $data_weapons[i]
  end
  
  def item(i)
    return @data_items[i]
  end
end 

 

 

 

Edited by Lisah

Share this post


Link to post
Share on other sites

Hello, I have a problem,,,

how can I fix this?

 

 

CryX2_zps32764764.jpg

 

 

how to change the inventory window opacity to zero?

 

*I'm indonesian, I'm sorry if I made a grammar mistakes*

Edited by Navest

Share this post


Link to post
Share on other sites

I'm not sure. I did not write my new set of inventory scripts with this in mind since this is old and not very good.

Share this post


Link to post
Share on other sites

Well I still like it tsutsu <3 I wonder if I should make my own version actually given how many tweeks and stuff I have made and how many scripts I made that sort of depend on it.

 

Anyway at a glance I would say... possibly! Given the Game_Inventory class exists for both systems if I remember right.

Edited by KilloZapit

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
Top ArrowTop Arrow Highlighted