KChest XP - kyonides - 09-05-2012
KChest XP
Version: 1.0.3
by Kyonides (Kyonides-Arkanthos)
Introduction
This script lets you easily create chests to store your items, weapons or armors or just all of your stuff. Of course you may take whatever is in those lonely and long forgotten chests. You are not supposed to animate the chests, it is already taken care of by the script.
Demo
No demo needed, just paste the script between Scene_Debug and Main and edit the Constants to get the results you want to get from it.
Instructions
Pick an empty slot to store any kind of item or weapon or armor. If you pick a chest item, it will automatically disappear and will be added to your team's "bag". And now please read the built-in instructions.
Script
Code: # KChest XP
# v 1.0.3 - 2012-09-08
# v 1.0.0 - 2012-09-04
# Scripter: Kyonides aka Kyonides-Arkanthos
# Create chests to retrieve or leave items, weapons, armors. There is no need
# to animate the chest by yourself, it is already taken care of.
# It may be used as a safe at a bank, too. Of course, you would need to create
# the engine and later ask the player for a (numeric) password.
# script calls:
# open_chest(variable_id)
# open_chest(variable_id, 'i10', 'w20', 'a8')
# opt=%w{i10 i22 w20 w40 a8 a27}
# open_chest(variable_id, opt)
# If you call the script by using the open_chest(variable_id), it will create
# a new chest with no contents. This is only valid for the very first time
# you use it. Thereafter the system will just get the contents of the
# $game_variables[variable_id] for you.
# GameSys module Constants will let you define the maximum slots per chest.
module GameSys
# String : The empty slot icon filename
EmptySlot = 'emptyslot'
# Integer : Starting $game_variables ID to be used to store chest contents
StartChestVarID = 5
# Integer : How many slots per row would like to be displayed on screen?
SlotPerRow = 5
# Boolean : Use the automatic variable ID conversion or not
ConvertVarID = true
# Integer => Integer : Variable ID => Maximum Slots for this chest
# If ConvertVarID is true, then start from number 1 as your first var ID
# Otherwise pick any variable ID at will but you would need to remember the
# exact variable ID you pick for your chest event.
ChestInfo = {1 => 1, 2 => 2, 3 => 4, 4 => 2, 5 => 5, 6 => 12}
def self.get_size_offset
s = RPG::Cache.icon(EmptySlot).rect
i = RPG::Cache.icon('021-Potion01').rect
@height, @width = s.height, s.width
@x_offset, @y_offset = @height - i.height, @width - i.width
RPG::Cache.clear
end
def self.slot_height; @height end
def self.slot_width; @width end
def self.slot_x_offset; @x_offset end
def self.slot_y_offset; @y_offset end
self.get_size_offset
end
module SpriteMod
def dispose; self.bitmap.dispose if self.bitmap != nil; super end
end
class Game_System
attr_reader :chest_sizes
alias kyon_use_chest_gm_sys_init initialize
def initialize
@chest_sizes = {}
GameSys::ChestInfo.each {|key, val|
key = GameSys::StartChestVarID + key - 1 if GameSys::ConvertVarID
@chest_sizes[key] = val
change_chest_size(@chest_sizes[key].size, key) }
kyon_use_chest_gm_sys_init
end
def change_chest_size(size, *vars)
vars.each {|var| next if @chest_sizes[var].size == size
@chest_sizes[var] = size
$game_variables[var] = [0] if $game_variables[var].is_a?(Fixnum)
size -= $game_variables[var].size - 1 if $game_variables[var].is_a?(Array)
$game_variables[var] += [[nil, nil]] * size }
end
end
class Game_Party
def all_items; @items + @weapons + @armors end
end
class Window_ChestItem < Window_Item
def initialize
super
@column_max = 2
self.index = 0
end
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
for i in 1...$data_items.size
@data.push($data_items[i]) if $game_party.item_number(i) > 0
end
for i in 1...$data_weapons.size
@data.push($data_weapons[i]) if $game_party.weapon_number(i) > 0
end
for i in 1...$data_armors.size
@data.push($data_armors[i]) if $game_party.armor_number(i) > 0
end
@item_max = @data.size
end
def items_size; @data.size end
def delete_at(index) @data.delete_at(index) end
def redraw_items
self.contents = Bitmap.new(width - 32, row_max * 32)
(0...@item_max).each {|i| draw_item(i)} if @data.size > 0
end
def draw_item(index)
item = @data[index]
case item
when RPG::Item; number = $game_party.item_number(item.id)
when RPG::Weapon; number = $game_party.weapon_number(item.id)
when RPG::Armor; number = $game_party.armor_number(item.id)
end
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = self.contents.font.color == normal_color ? 255 : 128
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
self.contents.draw_text(x + 240, y, 16, 32, ":", 1)
self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2)
end
end
class Arrow_Chest < Sprite
attr_accessor :index, :row_max, :item_max, :item_width, :x_y
def initialize(viewport, x=0, y=0)
super(viewport)
self.bitmap = RPG::Cache.windowskin($game_system.windowskin_name)
self.src_rect.set(128, 96, 32, 32)
self.z = 5000
self.x, self.y = x + 16, y
self.angle -= 90
@blink_count = 0
@index = 0
@row_max = 1
@item_max = 0
@item_width = 16
@x_y = nil
@name, @last_name = '', nil
@color = Color.new(120, 120, 120, 120)
end
def update
@blink_count = (@blink_count + 1) % 16
index = @blink_count < 8 ? 128 : 160
self.src_rect.set(index, 96, 32, 32)
if @last_name != @name
@name_sprite.bitmap.dispose unless @name_sprite.nil?
@name_sprite.bitmap = Bitmap.new(180, 28)
@name_sprite.bitmap.fill_rect(0, 0, 180, 28, @color)
@name_sprite.bitmap.draw_text(0, 0, 180, 28, @name, 1)
@last_name = @name
end
return if @item_max == 0
if Input.repeat?(Input::RIGHT)
$game_system.se_play($data_system.cursor_se)
@index = @index < @x_y.size - 1 ? @index + 1 : 0
self.x, self.y = @x_y[@index][0] + 16, @x_y[@index][1]
elsif Input.repeat?(Input::LEFT)
$game_system.se_play($data_system.cursor_se)
@index = @index > 0 ? @index - 1 : @x_y.size - 1
self.x, self.y = @x_y[@index][0] + 16, @x_y[@index][1]
end
end
def item_name=(name) @name = name; update end
def name_sprite=(sprite) @name_sprite = sprite end
end
class Interpreter
alias kyon_use_chest_int_up update
def update
kyon_use_chest_int_up
if @opened_chest and @wait_count == 0
$scene = Scene_KChest.new(@var_id, @items)
@opened_chest = @var_id = @items = nil
return
end
end
def open_chest(var, *items)
@wait_count = 20
@opened_chest = true
@var_id, @items = var, items
set_move_route_by_script(:open)
end
def set_move_route_by_script(move=:open)
$game_player.straighten
event = get_character(0)
if move == :open
event.turn_left
event.turn_right
event.turn_up
else
event.turn_right
event.turn_left
event.turn_down
end
end
end
class Spriteset_KChest
attr_reader :cursor, :spaces, :goods, :good_sprites
def initialize(var, *items)
if !items.nil?
index = -1
items.flatten.each {|item|kind = item[0,1]=='i'? 0 : item[0,1]=='w'? 1 : 2
item = item.sub(/\w/, '').to_i
name = case kind
when 0; $data_items[item].name
when 1; $data_weapons[item].name
when 2; $data_armors[item].name
end
items[index+=1] = [kind, item, name] }
end
var = GameSys::StartChestVarID + var - 1 if GameSys::ConvertVarID
@var_id = var
@spaces = $game_system.chest_sizes[@var_id]
@var = $game_variables[@var_id]
@goods = @var.is_a?(Array)? @var[0, @spaces] : items[0, @spaces]
@height, @width = GameSys.slot_height, GameSys.slot_width
@x_offset, @y_offset = GameSys.slot_x_offset, GameSys.slot_y_offset
@slot_sprites, @good_sprites = [], []
make_slot_sprites
make_good_sprites
@viewport = Viewport.new(0, 0, 640, 480)
@viewport.z = 5000
@cursor = Arrow_Chest.new(@viewport, @slot_sprites[0].x, @slot_sprites[0].y)
@cursor.row_max = GameSys::SlotPerRow
@cursor.item_max = @good_sprites.size + 1
@cursor.item_width = @slot_sprites[0].src_rect.width
update_cursor_coordinates
@name_sprite = Sprite.new
@name_sprite.bitmap = Bitmap.new(180, 28)
@name_sprite.x, @name_sprite.y = 230, @slot_sprites[0].y - 4 - @height
@cursor.name_sprite = @name_sprite
@cursor.item_name = item.nil? ? '' : item[2]
end
def item() @goods[@cursor.index] end
def make_slot_sprites
row_max = GameSys::SlotPerRow
free_space_x = (640 - ((@spaces < row_max ? @spaces : row_max)*@width)) / 2
free_space_y = (480 - @height - (@spaces /(row_max+1) * @height)) / 2
@spaces.times {|n| @slot_sprites << Sprite.new
@slot_sprites[n].extend SpriteMod
@slot_sprites[n].bitmap = RPG::Cache.icon(GameSys::EmptySlot)
h, w = @slot_sprites[n].bitmap.height, @slot_sprites[n].bitmap.width
@slot_sprites[n].x = free_space_x + (n % row_max * w)
@slot_sprites[n].y = free_space_y + (n / row_max * h)
@slot_sprites[n].opacity = 140 }
end
def make_good_sprites
@spaces.times {|n| kind, id = @goods[n]
break unless kind.is_a?(Integer)
i=kind==0? $data_items[id] : kind==1? $data_weapons[id] : $data_armors[id]
@good_sprites[n] = Sprite.new
@good_sprites[n].extend SpriteMod
@good_sprites[n].bitmap = RPG::Cache.icon(i.icon_name)
@good_sprites[n].x = @slot_sprites[n].x + (@x_offset / 2)
@good_sprites[n].y = @slot_sprites[n].y + (@y_offset / 2) }
end
def update
@cursor.item_name = item.nil? ? '' : item[2]
@name_sprite.update
@slot_sprites.each {|sprite| sprite.update}
@good_sprites.each {|sprite| sprite.update} unless @good_sprites.nil?
end
def update_cursor_coordinates
@cursor.item_max = @good_sprites.size
size = @good_sprites.size > 0 ? 1 : 0
@cursor.x_y = @slot_sprites.map {|s| [s.x, s.y]}[0, @good_sprites.size+size]
end
def update_goods(simple=false)
@goods.delete_at @cursor.index unless simple
$game_variables[@var_id] = @goods
end
def update_goods_all_sprites
$game_system.se_play($data_system.decision_se)
update_goods
dispose_good_sprites
make_good_sprites
update_cursor_coordinates
end
def dispose
@name_sprite.dispose
@slot_sprites.each {|s| s.dispose}
@slot_sprites.clear
dispose_good_sprites unless @good_sprites.nil?
update_goods(true)
@cursor.dispose
end
def dispose_good_sprites
@good_sprites.each {|s| s.dispose}
@good_sprites.clear
end
end
class Scene_KChest
def initialize(var, *items) @var, @items = var, items end
def main
start
Graphics.transition
loop do
Graphics.update
Input.update
update
break if $scene != self
end
Graphics.freeze
terminate
end
def start
@map_spriteset = Spriteset_Map.new
@spriteset = Spriteset_KChest.new(@var, @items)
@help_window = Window_Help.new
@help_window.visible = false
@item_window = Window_ChestItem.new
@item_window.active = @item_window.visible = false
@item_window.help_window = @help_window
end
def terminate
@spriteset.dispose
@map_spriteset.dispose
dispose_all_instance_variables
end
def update
@spriteset.update
(update_cursor_slots; return) unless @item_window.active
(update_item; return) if @item_window.active
end
def update_cursor_slots
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
$game_system.map_interpreter.set_move_route_by_script(:close)
return
elsif Input.trigger?(Input::C)
if (@spriteset.good_sprites.nil? and $game_party.all_items.keys.size == 0)
$game_system.se_play($data_system.buzzer_se)
return
end
item = @spriteset.item
if item.nil?
@item_window.refresh
return if @item_window.items_size == 0
@item_window.redraw_items
@spriteset.cursor.visible = false
@help_window.visible = @item_window.visible = @item_window.active = true
return
end
case item[0]
when 0; return if $game_party.item_number(item[1]) == 99
$game_party.gain_item(item[1], 1)
@spriteset.update_goods_all_sprites
@item_window.refresh
when 1; return if $game_party.weapon_number(item[1]) == 99
$game_party.gain_weapon(item[1], 1)
@spriteset.update_goods_all_sprites
@item_window.refresh
when 2; return if $game_party.armor_number(item[1]) == 99
$game_party.gain_armor(item[1], 1)
@spriteset.update_goods_all_sprites
@item_window.refresh
end
return
end
end
def update_item
@item_window.update
@help_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@spriteset.cursor.visible = true
@help_window.visible = @item_window.visible = @item_window.active = false
return
elsif Input.trigger?(Input::C)
if @spriteset.goods.size + 1 == @spriteset.spaces
$game_system.se_play($data_system.buzzer_se)
return
end
$game_system.se_play($data_system.decision_se)
@item = @item_window.item
case @item
when RPG::Item; $game_party.lose_item(@item.id, 1)
when RPG::Weapon; $game_party.lose_weapon(@item.id, 1)
when RPG::Armor; $game_party.lose_armor(@item.id, 1)
when nil; $game_system.se_play($data_system.buzzer_se); return
end
@item_window.delete_at @item_window.index
@item_window.redraw_items
kind = @item.is_a?(RPG::Item)? 0 : @item.is_a?(RPG::Weapon)? 1 : 2
@spriteset.goods << [kind, @item.id]
@spriteset.dispose_good_sprites
@spriteset.make_good_sprites
@spriteset.update_cursor_coordinates
end
end
def update_all_instance_variables
instance_variables.each {|var| ivar = instance_variable_get(var)
ivar.update if [Window, Sprite].include?(ivar) }
end
def dispose_all_instance_variables
instance_variables.each {|var| ivar = instance_variable_get(var)
ivar.dispose if [Window, Sprite, Viewport].include?(ivar) }
end
end
FAQ
Version 1.0.0 - Keep in mind that you may need to create a 36*36 pixel icon for the script to work properly.
Version 1.0.1 and later - Now you may use an icon of any size >= 24 * 24 pixels for the script to work properly.
As for now the icon should be named emptyslot.png but you can edit this by changing the EmptySlot filename string inside the GameSys module section of the script.
Compatibility
Designed for RPG Maker XP.
Terms and Conditions
Free for use but not meant for commercial projects. Due credit is not optional but a must.
RE: KChest XP - kyonides - 09-07-2012
Small Update!
Version 1.0.3 - Now you may use an icon of any size >= 24 * 24 pixels for the script to work properly. The filename should be emptyslot.png but you may edit it in the GameSys module section of the script at any time. Now you can also read the chosen item name right above the chest slots sprites.
RE: KChest XP - Narzew - 09-10-2012
Small, but good script. I'm used it to simplify my work with project :-)
|