Tsukihime 1,489 Posted March 7, 2013 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
Kayzee 4,032 Posted March 7, 2013 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
Tsukihime 1,489 Posted March 7, 2013 (edited) 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 March 7, 2013 by Tsukihime Share this post Link to post Share on other sites
Kayzee 4,032 Posted March 7, 2013 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
Tsukihime 1,489 Posted March 8, 2013 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
Kayzee 4,032 Posted March 8, 2013 (edited) 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 March 8, 2013 by KilloZapit Share this post Link to post Share on other sites
Tsukihime 1,489 Posted March 8, 2013 (edited) 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 March 8, 2013 by Tsukihime Share this post Link to post Share on other sites
Kayzee 4,032 Posted March 8, 2013 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
masterp 0 Posted May 9, 2013 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
masterp 0 Posted May 10, 2013 (edited) 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 May 10, 2013 by masterp Share this post Link to post Share on other sites
esrann 1 Posted May 10, 2013 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
Aishi 0 Posted May 10, 2013 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
masterp 0 Posted May 11, 2013 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
esrann 1 Posted May 20, 2013 Here's a screenshot of the common event I use: 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
masterp 0 Posted May 21, 2013 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
BOSSBERRY 28 Posted June 17, 2013 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
Tsukihime 1,489 Posted June 17, 2013 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
ricardo.jl.simoes 2 Posted July 12, 2013 (edited) 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 July 13, 2013 by ricardo.jl.simoes Share this post Link to post Share on other sites
+ TheDarkKnight 9 Posted July 26, 2013 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
Lisah 2 Posted August 5, 2013 (edited) 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! =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 August 5, 2013 by Lisah Share this post Link to post Share on other sites
Navest 4 Posted August 13, 2013 (edited) Hello, I have a problem,,, how can I fix this? how to change the inventory window opacity to zero? *I'm indonesian, I'm sorry if I made a grammar mistakes* Edited August 13, 2013 by Navest Share this post Link to post Share on other sites
+ Shadow Fox 5 Posted August 19, 2013 I too would like those two windows either removed fully or the opacity to 0 as well. Share this post Link to post Share on other sites
Metalhead33 0 Posted September 29, 2013 Sorry for necroposting, but may I ask if this script of yours compatible with this other script of yours, or not? Share this post Link to post Share on other sites
Tsukihime 1,489 Posted October 1, 2013 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
Kayzee 4,032 Posted October 1, 2013 (edited) 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 October 1, 2013 by KilloZapit Share this post Link to post Share on other sites