FP Inventory Plus?

kirby3012kirby3012 Posts: 27Registered
Hiện giờ cứ mỗi khi mình add thêm item, armor hay weapon là nó lại bị lỗi:
9ed3e889c2933f2756340f3b7da47e94_53948974.1.png
ai biết chỉ mình với
Mình đã config lại script như thế này, không thay đổi trừ hàng 71,76,77,97. Bạn nào biết không, chỉ mình với.
=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 = true
Use_Weight_Limit = false

# 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 = 9999
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 = "%s/%s %s"

# [item_count] / [item_limit]
Item_Display = "Items: %s/%s"

# Inventory limit defaults
Inventory_Limit = 30 #max inventory size
Weight_Limit = 2000000 #max inventory weight

#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
@weight_limit = Weight_Limit
end

def max_items
@inventory_limit
end

def max_weight
@weight_limit
end

def weight_exceeded?(item)
return false unless Feature_Plus::Inventory_System::Use_Weight_Limit
@weight + item.item_weight > @weight_limit
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
Weight_Limit
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 = Game_Item.new(item, i) if item.is_a?(RPG::Item)
@stacks = Game_Weapon.new(item, i) if item.is_a?(RPG::Weapon)
@stacks = 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.nil?
stack = @stacks
amt = stack.amount_can_add?
@stacks.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.count == 0
stack = @stacks
lost_amount = stack.lose_amount(amount)
delete_stack(i) if @stacks.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 = 48
if Feature_Plus::Inventory_System::Use_Weight_Limit
@weight_window = Window_Weight.new(0, 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
end

def weapon(i)
return $data_weapons
end

def item(i)
return @data_items
end
end

Comments

Sign In or Register to comment.