Code:
# * KSingleItemShop XP * #
# Scripter : Kyonides
# v0.6.1 - 2025-04-27
# Create a special shop that only offers single items on its shelves.
# To keep them separate from normal shops, turn on a specific switch and set
# the shop's ID via a specific variable.
# The script also features the ability of creating purchase-only shops.
# It also allows you to set a backdrop as well instead of the current map.
# The rest is taken care by the script.
module KSingleItem
PURCHASE_ONLY_SWITCH = 9
SHOP_SWITCH = 10
SHOP_ID_VAR = 10
DEFAULT_BACKDROP = "012-PortTown02"
class Shop
attr_accessor :goods
end
end
class Game_Party
alias :kyon_single_item_gm_pty_init :initialize
def initialize
kyon_single_item_gm_pty_init
@single_shops = {}
end
def setup_single_shop(shop_id, new_goods)
shop = @single_shops[shop_id] || KSingleItem::Shop.new
shop.goods = new_goods
end
attr_reader :single_shops
end
class Window_ShopBuy
attr_reader :shop_goods
def initialize(shop_goods)
w = 368
@tw = w - 64
super(0, 288, w, 192)
@shop_goods = shop_goods.dup
@no_item = RPG::Item.new
@transparent = Color.new(0, 0, 0, 0)
@symbol_color = Color.new(255, 255, 80)
@symbol = $data_system.words.gold
refresh
self.index = 0
end
def item
@data[@index] || @no_item
end
def item_name
self.item.name
end
def set_goods(goods_item)
type, goods_id = goods_item
case type
when 0
$data_items[goods_id]
when 1
$data_weapons[goods_id]
when 2
$data_armors[goods_id]
end
end
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
for goods_item in @shop_goods
item = set_goods(goods_item)
@data << item if item
end
draw_items
end
def draw_items
@item_max = @data.size
self.contents = Bitmap.new(width - 32, row_max * 32) if @item_max > 0
@item_max.times {|i| draw_item(i) }
end
def clear_line(rx, ry)
rect = Rect.new(rx, ry, self.width - 32, 32)
self.contents.fill_rect(rect, @transparent)
end
def draw_item(index)
item = @data[index]
font = self.contents.font
if item.price <= $game_party.gold
font.color = normal_color
opacity = 255
else
font.color = disabled_color
opacity = 128
end
ry = index * 32
clear_line(4, ry)
bitmap = RPG::Cache.icon(item.icon_name)
self.contents.blt(28, ry + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(56, ry, @tw - 100, 32, item.name)
self.contents.draw_text(@tw - 92, ry, 100, 32, item.price.to_s, 2)
@symbol_color.alpha = opacity
font.color = @symbol_color
self.contents.draw_text(@tw, ry, 24, 32, @symbol, 2)
end
def update_help
@help_window.set_text(self.item.description)
end
def delete_item
@shop_goods.delete(@index)
item = @data.delete(@index)
self.contents.dispose if self.contents != nil
self.contents = nil
draw_items
end
end
class Scene_Map
def call_shop
$game_temp.shop_calling = false
$game_player.straighten
if $game_switches[KSingleItem::SHOP_SWITCH]
$scene = SingleShopScene.new
else
$scene = Scene_Shop.new
end
end
end
class SingleShopScene < Scene_Shop
include KSingleItem
def find_shop_id
$game_variables[SHOP_ID_VAR]
end
def main
prepare_goods
make_backdrop
make_windows
Graphics.transition
loop do
Graphics.update
Input.update
update
if $scene != self
break
end
end
Graphics.freeze
dispose_windows
reset_single_shop
end
def prepare_goods
shop_id = find_shop_id
shop = $game_party.single_shops[shop_id]
@goods = shop ? shop.goods : $game_temp.shop_goods
end
def make_backdrop
@backdrop = Sprite.new
@backdrop.bitmap = RPG::Cache.battleback(DEFAULT_BACKDROP)
end
def make_windows
@help_window = Window_Help.new
@command_window = Window_ShopCommand.new
@command_window.disable_item(1) if $game_switches[PURCHASE_ONLY_SWITCH]
@gold_window = Window_Gold.new
@gold_window.x = 480
@gold_window.y = 64
@dummy_window = Window_Base.new(0, 288, 640, 192)
@buy_window = Window_ShopBuy.new(@goods)
@buy_window.active = false
@buy_window.visible = false
@buy_window.help_window = @help_window
@sell_window = Window_ShopSell.new
@sell_window.active = false
@sell_window.visible = false
@sell_window.help_window = @help_window
@number_window = Window_ShopNumber.new
@number_window.active = false
@number_window.visible = false
@status_window = Window_ShopStatus.new
@status_window.visible = false
end
def update_command
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return
elsif Input.trigger?(Input::C)
case @command_window.index
when 0
open_purchase
when 1
if $game_switches[PURCHASE_ONLY_SWITCH]
$game_system.se_play($data_system.buzzer_se)
return
end
open_sale
when 2
$game_system.se_play($data_system.decision_se)
$scene = Scene_Map.new
end
end
end
def open_purchase
$game_system.se_play($data_system.decision_se)
@command_window.active = false
@dummy_window.visible = false
@buy_window.active = true
@buy_window.visible = true
@buy_window.refresh
@status_window.visible = true
end
def open_sale
$game_system.se_play($data_system.decision_se)
@command_window.active = false
@dummy_window.visible = false
@sell_window.active = true
@sell_window.visible = true
@sell_window.refresh
end
def dispose_windows
@backdrop.bitmap.dispose
@backdrop.dispose
@help_window.dispose
@command_window.dispose
@gold_window.dispose
@dummy_window.dispose
@buy_window.dispose
@sell_window.dispose
@number_window.dispose
@status_window.dispose
end
def reset_single_shop
list = @buy_window.shop_goods
return list.size == @goods.size
shop_id = find_shop_id
return if shop_id == 0
$game_party.setup_single_shop(shop_id, @buy_window.shop_goods)
$game_variables[SHOP_ID_VAR] = 0
$game_switches[PURCHASE_ONLY_SWITCH] = false
$game_switches[SHOP_SWITCH] = false
end
end