Item Instances Base Version: 1.0.0 Author: modern algebra Date: 26 December 2012
Version History
<Version 1.0> 2012.12.26 - Original Release Description
This script changes the item system in RMVX Ace to accomodate for items of the same ID to have different stats. It can thereby serve as a base for scripts that require such functionality, such as durability for weapons and armors, charges for items, weapons that level up, socketing, etc...
This script does none of that by default - it only sets up data structures to permit that, and its only independent use is that you can manually change the stats on an item added to the party through events.
Features
Allows for items of the same ID to be saved as instances. A useful base for other scripts which require that functionality, such as durability scripts, socketing, enchanting items, levelling weapons, etc. Instructions
Insert this script into its own slot in the Script Editor, above Main but below Materials. This script must also be above every script that requires it.
Script
#============================================================================== # Instance Items Base [VXA] # Version: 1.0.0 # Author: modern algebra (rmrk.net) # Date: 26 December 2012 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Description: # # This script changes the item system in RMVX Ace to accomodate for items # of the same ID to have different stats. It can thereby serve as a base for # scripts that require such functionality, such as durability for weapons and # armors, charges for items, weapons that level up, socketing, etc... # # This script does none of that by default - it only sets up data structures # to permit that, and its only independent use is that you can manually # change the stats on an item added to the party through events. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Instructions: # # Insert this script into its own slot in the Script Editor, above Main but # below Materials. This script must also be above every script that requires # it. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Instructions for Scripters: # # If you are a scripter and want to write a script that requires this script # in order to be used, you have my permission. I ask only that you link back # to this script at RMRK, as well as provide me with a link to your script so # that I can ensure compatibility. # # I have tried to comment the script where there might be some confusion, # so you should be able to read through it to gain an understanding as to # how it works. For the most part, it is designed to mimic as much as # possible the default arrangement. So, if you access the first 999 indices # of $data_items, $data_weapons, or $data_armors, you will receive the basic # classes for those. New instances begin at ID 1000, and each new instance # will have a unique ID, which is what is returned when you call the #id # method. Instances will also have a #database_id method which returns the # ID of its base item. Instance items are now of the Game_IItem, Game_IWeapon, # or Game_IArmor. Game_IItem inherits its methods from the module # Game_IUsableItem, and the others inherit from the module Game_IEquipItem. # Both Game_IEquipItem and Game_IUsableItem inherit from Game_IBaseItem. # # If you need to add a new notefield tag, it is recommended you also add it # to MA_INSTANCE_ITEMS_BASE[:regexp_array], as any regular expressions # included in that array will make the #instance_based? method in # RPG::BaseItem return true if the item has that in its note field. # # Beyond that, I recommend you read the entire script in order to gain an # understanding of how it works. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Support: # # If you have any questions, feel free to ask them in the script's topic: # # http://rmrk.net/index.php/topic,47427.0.html # # I will try to answer as swiftly as possible. If you believe further # documentation is required, please let me know. #============================================================================== $imported = {} unless $imported $imported[:"MA_InstanceItemsBase 1.0.0"] = true MA_INSTANCE_ITEMS_BASE = { # This sets the first index used for instance items. It should be 1000 # unless you are using another script which makes extends the database # limitations beyond 999. :index_start => 1000, # This array tracks the note field codes which identify that an item should # be created as new instances. :regexp_array => [/\\INS/i], # This array holds methods which you would never want to distinguish between # instances :ignore_accessors => [], } #============================================================================== # ** MAIIB_RPG_BaseItem #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This mixes in to RPG::Item, RPG::Weapon, and RPG::Armor, adding the # following methods: # overwritten method - == # new methods - instance_based?; database_id #============================================================================== module MAIIB_RPG_BaseItem #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Instance Based? # This is true if the item is identified as instance-based. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def instance_based? @ins_based = MA_INSTANCE_ITEMS_BASE[:regexp_array].any? { |regexp| !self.note[regexp].nil? } unless @ins_based @ins_based end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Data ID # Essentially just aliases #id, but in case any other script overwrites # or aliases #id, I made it so it just calls it #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def database_id(*args, &block) id(*args, &block) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Equality? # Also returns true if other is an instance item with same data. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def ==(other) super(other) || (other.is_a?(Game_BaseInstanceItem) && super(other.data)) end end # MAIIB_RPG_UsableItem and MAIIB_RPG_EquipItem both inherit MAIIB_RPG_BaseItem module MAIIB_RPG_UsableItem; include MAIIB_RPG_BaseItem; end module MAIIB_RPG_EquipItem; include MAIIB_RPG_BaseItem; end module RPG class Item; include MAIIB_RPG_UsableItem; end class Weapon; include MAIIB_RPG_EquipItem; end class Armor; include MAIIB_RPG_EquipItem; end end #============================================================================== # *** DataManager #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # These modifications preserve the #`````````````````````````````````````````````````````````````````````````````` # Summary of Changes: # aliased methods - init; extract_save_contents; create_game_objects # new method - maiib_preserve_old_saves; set_data_to_instance_items #============================================================================== class << DataManager #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Initialize #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_inz_2tg6 init def init(*args, &block) Game_BaseInstanceItem.init_auto_accessors # Initialize automatic maiib_inz_2tg6(*args, &block) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Extract Save Contents #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_extractsave_2jw6 extract_save_contents def extract_save_contents(contents, *args, &block) maiib_extractsave_2jw6(contents, *args, &block) # Call Original Methods maiib_preserve_old_saves end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Create Game Objects #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_creatgameobj_4hi8 create_game_objects def create_game_objects(*args, &block) maiib_creatgameobj_4hi8(*args, &block) # Call Original Method set_data_to_instance_items end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Preserve Save Contents #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def maiib_preserve_old_saves $game_system.init_maiib_data unless $game_system.instance_items set_data_to_instance_items end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Set Data Instance Items #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def set_data_to_instance_items $game_system.instance_items[:item].reset_data_array($data_items) $game_system.instance_items[:weapon].reset_data_array($data_weapons) $game_system.instance_items[:armor].reset_data_array($data_armors) $data_items = $game_system.instance_items[:item] $data_weapons = $game_system.instance_items[:weapon] $data_armors = $game_system.instance_items[:armor] end end #============================================================================== # ** Game_BaseInstanceItem #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This class holds an instance of an Item, Weapon, or Armor #============================================================================== module Game_BaseInstanceItem #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Public Instance Variables #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ attr_writer :id attr_accessor :data_type attr_accessor :database_id #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Object Initialization #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def initialize(id, data_type, database_id) @id = id @data_type = data_type @database_id = database_id self.class.auto_accessors.each { |method| instance_variable_set(:"@#{method}", Marshal.load(Marshal.dump(data.send(method)))) } end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Get ID #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def id ($game_system && $game_system.retrieve_database_id) ? database_id : @id end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Data #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def data case data_type when :item then $data_items[database_id] when :weapon then $data_weapons[database_id] when :armor then $data_armors[database_id] end end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Method Missing #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def method_missing(method, *args, &block) if method.to_s[/^(.*?[^=])=$/] && !MA_INSTANCE_ITEMS_BASE[:ignore_accessors].include?(method) instance_exec($1.to_sym) { |new_meth| eval("def #{new_meth}=(val); @#{new_meth} = val; end; def #{new_meth}; @#{new_meth}; end") } send(method, *args, &block) else data ? data.send(method, *args, &block) : super(method, *args, &block) end end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Equality? #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def ==(other); super(other) || (data && data == other); end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Is A? #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def is_a?(*args, &block) super(*args, &block) || (data && data.is_a?(*args, &block)) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Initialize All Automatic Accessors #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def self.init_auto_accessors # For all descendants ObjectSpace.each_object(Class) { |klass| klass.class_eval { klass.auto_accessors.each { |method| attr_accessor(method) } } if klass < self } end end module Game_IUsableItem; include Game_BaseInstanceItem; end module Game_IEquipItem; include Game_BaseInstanceItem; end class Game_IItem include Game_IUsableItem def initialize(*args); super(*args); end def self.auto_accessors; [:effects]; end end class Game_IWeapon include Game_IEquipItem def initialize(*args); super(*args); end def self.auto_accessors; [:params, :features]; end end class Game_IArmor include Game_IEquipItem def initialize(*args); super(*args); end def self.auto_accessors; [:params, :features]; end end #============================================================================== # ** Game_InstanceItems #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This is a special subclass of an array which holds instance items in a # separate hashes. It replaces the $data_ classe for items, weapons, and armors #============================================================================== class Game_InstanceItems < Array #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Public Instance Variables #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ attr_accessor :instance_items #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Object Initialization #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def initialize(type, data_array = []) @instance_items = {} @type = type @index_start = MA_INSTANCE_ITEMS_BASE[:index_start] @last_index = @index_start @free_indices = [] reset_data_array(data_array) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Type Class #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def type_class case @type when :item then Game_IItem when :weapon then Game_IWeapon when :armor then Game_IArmor end end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Reset Data Array #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def reset_data_array(data_array) clear for item in data_array do self << item end end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Create Instance #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def create_instance(base_item) base_item = self[base_item] if base_item.is_a?(Integer) return base_item if base_item.is_a?(Game_BaseInstanceItem) || !base_item.instance_based? # Get next free index if @free_indices.empty? index = @last_index @last_index += 1 else index = @free_indices.shift end @instance_items[index] = type_class.new(index, @type, base_item.id) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Destroy Instance #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def destroy_instance(index) @free_indices.push(index) @instance_items.delete(index) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Retrieve Value from key #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def [](key) return key < @index_start ? super(key) : @instance_items[key] end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Set Value to Key #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def []=(key, value) key < @index_start ? super(key, value) : @instance_items[key] = value end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Items with ID # This will return an array of all items with the specified ID #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def items_with_id(item_id) return [self[item_id]] unless self[item_id].instance_based? return @instance_items.values.select { |ins| ins.item_id == item_id } end end #============================================================================== # ** Game_System #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Summary of Changes: # new attr_reader - instance_items # new attr_accessor - retrieve_database_id # aliased method - initialize # new method - init_maiib_data #============================================================================== class Game_System #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Public Instance Variables #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ attr_reader :instance_items attr_accessor :retrieve_database_id #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Object Initialization #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_intz_2sh7 initialize def initialize(*args, &block) maiib_intz_2sh7(*args, &block) # Call Original Method init_maiib_data end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Initialize Instance Items Base Data #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def init_maiib_data @instance_items = { item: Game_InstanceItems.new(:item), weapon: Game_InstanceItems.new(:weapon), armor: Game_InstanceItems.new(:armor) } @retrieve_database_id = false end end #============================================================================== # ** Game_BaseItem #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Summary of Changes: # aliased method - set_equip; is_item?; is_weapon?; is_armor? #============================================================================== class Game_BaseItem #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Is Item/Weapon/Armor? #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [:Item, :Weapon, :Armor].each { |ic| alias_method(:"maiib_is_#{ic.downcase}_8jf9", :"is_#{ic.downcase}?") define_method(:"is_#{ic.downcase}?") do |*args| send(:"maiib_is_#{ic.downcase}_8jf9", *args) || @class == Kernel.const_get(:"Game_I#{ic}") end } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Set Equipment #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_seteqp_1gn8 set_equip def set_equip(is_weapon, item_id, *args, &block) data = is_weapon ? $data_weapons : $data_armors item_id = data.create_instance(item_id).id if data[item_id] && !data[item_id].is_a?(Game_BaseInstanceItem) && data[item_id].instance_based? maiib_seteqp_1gn8(is_weapon, item_id, *args, &block) # Call Original Method end end #============================================================================== # ** Game_Party #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Summary of Changes: # aliased methods - initialize; items; weapons; armors; item_container; # item_number; members_equip_include?; gain_item; discard_members_equip # new methods - instance_item_container; instance_item_type; # instance_item_number; gain_instance_item #============================================================================== class Game_Party #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Public Instance Variables #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ attr_reader :newest_instance_items #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Object Initialization #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_nitialz_4ld5 initialize def initialize(*args, &block) @newest_instance_items = [] maiib_nitialz_4ld5(*args, &block) # Call Original Method end [:items, :weapons, :armors].each { |method| #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Items/Weapons/Armors #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias_method(:"maiib_#{method}_3js6", method) define_method(method) do |*args| result = send(:"maiib_#{method}_3js6", *args) # Call Original Method # Delete the database items if they are instance items deletables = [] for i in 0...result.size item = result[i] next if item.nil? break if item.is_a?(Game_BaseInstanceItem) deletables << i if item.instance_based? end deletables.reverse.each { |i| result.delete_at(i) } # Sort by Database ID, then ID. result.sort {|a, b| (a.database_id <=> b.database_id).nonzero? || a.id <=> b.id } end } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Held Instances Of # item : the Item to check #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def held_instances_of(item) maiib_items_of_type(item).select { |item2| item2.database_id == item.database_id } end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Item Container #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_itmcontain_7hq9 item_container def item_container(item_class, *args, &block) return @items if item_class == Game_IItem return @weapons if item_class == Game_IWeapon return @armors if item_class == Game_IArmor maiib_itmcontain_7hq9(item_class, *args, &block) # Call Original Method end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Items of Type #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def maiib_items_of_type(item) case instance_item_type(item) when :item then items when :weapon then weapons when :armor then armors else [] end end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Instance Type #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def instance_item_type(item) case item when RPG::Item, Game_IItem then :item when RPG::Weapon, Game_IWeapon then :weapon when RPG::Armor, Game_IArmor then :armor end end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Gain Item #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_gainitm_3ky7 gain_item def gain_item(item, amount, include_equip = false, *args, &block) return if amount == 0 if item.is_a?(MAIIB_RPG_BaseItem) && item.instance_based? count = item_number(item) amount = [[amount, max_item_number(item) - count].min, 0].max if amount > 0 gain_instance_item(item, amount, include_equip) # Add the new items to the container @newest_instance_items.each { |ins| maiib_gainitm_3ky7(ins, amount <=> 0, include_equip) } # Prepare for database count item = item.data if item.is_a?(Game_BaseInstanceItem) end # Call Original Method and modify the count for database items maiib_gainitm_3ky7(item, amount, include_equip, *args, &block) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Gain Instance Item #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def gain_instance_item(item, amount, include_equip = false) @newest_instance_items.clear if item.is_a?(Game_BaseInstanceItem) if amount > 0 || (item_number(item) > 0 && amount < 0) # Add the item @newest_instance_items << item amount -= amount <=> 0 end # If amount was not 1 or -1, apply method to the database item item = item.data end return unless item if amount > 0 # Create new instances add_instance_items(item, amount) elsif amount < 0 # Find and remove instances of the same database item subtract_instance_items(item, -amount, include_equip) end end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Lose Instance Item #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def lose_instance_item (item, amount, include_equip = false) gain_instance_item(item, -amount, include_equip) end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Add Instance Item #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def add_instance_items(item, amount) data_array = $game_system.instance_items[instance_item_type(item)] amount.times { @newest_instance_items << data_array.create_instance(item) } end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Subtract Instance Item #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def subtract_instance_items(item, amount, include_equip = false) data_array = $game_system.instance_items[instance_item_type(item)] for ins in held_instances_of(item) break if amount == 0 @newest_instance_items << ins amount -= 1 end # Rely on discard_members_equip to dispose of equipped items end #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * Discard Members Equip #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ alias maiib_discardequip_3hx7 discard_members_equip def discard_members_equip(item, amount, *args, &block) if item.is_a?(MAIIB_RPG_BaseItem) && item.instance_based? && !item.is_a?(Game_BaseInstanceItem) n = amount members.each { |actor| while n > 0 ins = actor.equips.find { |equip| equip.database_id == item.database_id } break unless ins @newest_instance_items << ins actor.discard_equip(ins) n -= 1 end } else # Call Original Method maiib_discardequip_3hx7(item, amount, *args, &block) end end end
Credit
Support
Please post in this topic at RMRK.net if you have any questions, suggestions, error reports, or comments about this script. Please do not message me privately, as it is more efficient and useful to answer any concerns you have in the topic where others may benefit from our correspondence. Additionally, others might be able to provide you with quicker answers to your questions, as I am occasionally unavailable due to work.
Known Compatibility Issues
This script will likely not work with any other script which purports to do the same thing.
Spoiler for Yanfly's Ace Equip Engine :
There is a small bug in Yanfly's
Ace Equip Engine . Although it works functionally, when scrolling through instances of the same item, differences in stats will not be shown unless it is the first one you select after looking at some other item.
ekomega investigated the problem and determined that all you need to do to fix this error is to find line 1098 in Yanfly's script, which should look like this:
#-------------------------------------------------------------------------- # overwrite method: update_help #-------------------------------------------------------------------------- def update_help super return if @actor.nil? return if @status_window.nil? return if @last_item == item @last_item = item temp_actor = Marshal.load(Marshal.dump(@actor)) temp_actor.force_change_equip(@slot_id, item) @status_window.set_temp_actor(temp_actor) end
All you need to do is comment out or delete the following line:
return if @last_item == item
As far as I know, that should not cause any problems re: lag, since I don't believe that method is called except when the help window is likely to require updating. However, if deleting the line altogether makes you nervous, then you can replace it with:
return if @last_item.equal?(item)
Many thanks to ekomega for discovering and fixing this incompatibility.
Demo
This script does nothing on its own, so a demo would have no purpose.
Author's Notes
I actually finished this a few months ago, but then did not do anything with it as I planned to write a few sample scripts before releasing it. I never did that, so I let it stagnate for a while. Unfortunately, this means I am not entirely certain that it was actually finished, but I think it is. Please let me know if anything is missing.
Terms of Use
I adopt RMRK's default
Terms of Use .