Save-Point
KustomPriceShop XP - Printable Version

+- Save-Point (https://www.save-point.org)
+-- Forum: Material Development (https://www.save-point.org/forum-8.html)
+--- Forum: Scripts Database (https://www.save-point.org/forum-39.html)
+---- Forum: RPGMaker XP (RGSS) Engine (https://www.save-point.org/forum-116.html)
+---- Thread: KustomPriceShop XP (/thread-13479.html)



KustomPriceShop XP - kyonides - 05-17-2026

KustomPriceShop XP

by Kyonides

Introduction

This script allows you to open a special shop on a given map that offers:
  • Single items on its shelves.
  • Setting custom (buy or sale) prices for specific items.
  • Creating buy-only or sell-only shops.

To keep it separate from normal shops, set the shop's ID via a game variable.

You can change the maximum number of units per item allowed in your game.

It also lets you to set a backdrop as well instead of the current map.

EVENT SCREENSHOT

Optional Script Calls For The Active Shop

NOTE: ItemID stands for an actual positive number, starting from 1 onwards.

Add Items with Custom Prices:
Code:
buy_price_items(ItemID1 => Price1, etc.)
sell_price_items(ItemID1 => Price1, etc.)

Add Weapons with Custom Prices:
Code:
buy_price_weapons(WeaponID1 => Price1, etc.)
sell_price_weapons(WeaponID1 => Price1, etc.)

Add Armors with Custom Prices:
Code:
buy_price_armors(ArmorID1 => Price1, etc.)
sell_price_armors(ArmorID1 => Price1, etc.)

The Script

Code:
# * KustomPriceShop XP * #
#  Scripter : Kyonides
#  v0.9.0 - 2026-05-17

# Create a special shop that offers:
# - Single items on its shelves.
# - Setting custom prices for specific items.
# - Creating purchase-only or sell-only shops.

# To keep it separate from normal shops, set the shop's ID via a game variable.
# You can change the maximum number of units per item allowed in your game.
# It also allows you to set a backdrop as well instead of the current map.

# * Optional Script Calls For The Active Shop * #

# - Add Items with Custom Prices:
# buy_price_items(ItemID1 => Price1, etc.)
# sell_price_items(ItemID1 => Price1, etc.)

# - Add Weapons with Custom Prices:
# buy_price_weapons(WeaponID1 => Price1, etc.)
# sell_price_weapons(WeaponID1 => Price1, etc.)

# - Add Armors with Custom Prices:
# buy_price_armors(ArmorID1 => Price1, etc.)
# sell_price_armors(ArmorID1 => Price1, etc.)

module KustomPrice
  ITEM_MAX = 99
  BUY_ONLY_SWITCH  = 8
  SELL_ONLY_SWITCH = 9
  SHOP_ID_VAR = 10
  DEFAULT_BACKDROP = "012-PortTown02"

  class Shop
    attr_accessor :goods
  end

  extend self
  attr_reader :buy_item_prices, :buy_weapon_prices, :buy_armor_prices
  attr_reader :sell_item_prices, :sell_weapon_prices, :sell_armor_prices
  def buy_items(data={})
    @buy_item_prices = data
  end

  def buy_weapons(data={})
    @buy_weapon_prices = data
  end

  def buy_armors(data={})
    @buy_armor_prices = data
  end

  def sell_items(data={})
    @sell_item_prices = data
  end

  def sell_weapons(data={})
    @sell_weapon_prices = data
  end

  def sell_armors(data={})
    @sell_armor_prices = data
  end

  def clear_prices!
    @buy_item_prices = {}
    @buy_weapon_prices = {}
    @buy_armor_prices = {}
    @sell_item_prices = {}
    @sell_weapon_prices = {}
    @sell_armor_prices = {}
  end
  clear_prices!
end

class Game_Party
  alias :kyon_single_item_gm_pty_init :initialize
  def initialize
    kyon_single_item_gm_pty_init
    @custom_price_shops = {}
  end

  def setup_price_shop(shop_id, new_goods)
    shop = @custom_price_shops[shop_id] || KustomPrice::Shop.new
    shop.goods = new_goods
  end

  def bag_items
    @items
  end

  def bag_weapons
    @weapons
  end

  def bag_armors
    @armors
  end

  def compact_bag_items!
    @items.delete_if {|k,v| v == 0 }
    @weapons.delete_if {|k,v| v == 0 }
    @armors.delete_if {|k,v| v == 0 }
  end
  attr_reader :custom_price_shops
end

class Window_ShopCommand
  def reset_disabled_items
    @disabled = []
  end

  def disable_current_item?
    @disabled[@index]
  end
end

module KustomPrice
  module AddMethods
    def item
      @data[@index] || @no_item
    end

    def price
      @prices[@index] || 0
    end

    def get_price(n, item_id, price)
      case @types[n]
      when 0
        @item_prices[item_id] || price
      when 1
        @weapon_prices[item_id] || price
      when 2
        @armor_prices[item_id] || price
      end
    end
  end

class ShopBuyWindow < Window_Selectable
  include AddMethods
  attr_reader :shop_goods
  def initialize(shop_goods)
    w = 368
    @tw = w - 64
    super(0, 288, w, 192)
    setup_prices
    @shop_goods = shop_goods.dup
    @disabled = []
    @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 setup_prices
    @item_prices = KustomPrice.buy_item_prices
    @weapon_prices = KustomPrice.buy_weapon_prices
    @armor_prices = KustomPrice.buy_armor_prices
  end

  def item_name
    self.item.name
  end

  def set_goods(goods_item)
    type, goods_id = goods_item
    case type
    when 0
      [type, $data_items[goods_id]]
    when 1
      [type, $data_weapons[goods_id]]
    when 2
      [type, $data_armors[goods_id]]
    end
  end

  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @types = []
    @data = []
    @prices = []
    for goods_item in @shop_goods
      type, item = set_goods(goods_item)
      next unless item
      n = @types.size
      @types << type
      @data << item
      @prices << get_price(n, item.id, item.price)
    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(n)
    item = @data[n]
    font = self.contents.font
    price = @prices[n]
    if $game_party.gold >= price
      font.color = normal_color
      alpha = 255
    else
      font.color = disabled_color
      alpha = 128
    end
    ry = n * 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), alpha)
    self.contents.draw_text(56, ry, @tw - 100, 32, item.name)
    self.contents.draw_text(@tw - 92, ry, 100, 32, price.to_s, 2)
    @symbol_color.alpha = alpha
    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

  def disable_item(n)
    draw_item(n, disabled_color)
    @disabled[n] = true
  end
end

class ShopSellWindow < Window_Selectable
  include AddMethods
  def initialize
    super(0, 128, 640, 352)
    @column_max = 2
    @no_item = RPG::Item.new
    setup_prices
    refresh
    self.index = 0
  end

  def setup_prices
    @item_prices = KustomPrice.sell_item_prices
    @weapon_prices = KustomPrice.sell_weapon_prices
    @armor_prices = KustomPrice.sell_armor_prices
  end

  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @types = []
    @data = []
    @prices = []
    n = 0
    $game_party.bag_items.sort.each do |k,v|
      next if $game_party.item_number(k) == 0
      @types << 0
      @data << obj = $data_items[k]
      @prices << get_price(n, k, obj.price / 2)
      n += 1
    end
    $game_party.bag_weapons.sort.each do |k,v|
      next if $game_party.weapon_number(i) == 0
      @types << 1
      @data << obj = $data_weapons[k]
      @prices << get_price(n, k, obj.price / 2)
      n += 1
    end
    $game_party.bag_armors.sort.each do |k,v|
      next if $game_party.armor_number(i) == 0
      @types << 2
      @data << obj = $data_armors[k]
      @prices << get_price(n, k, obj.price / 2)
      n += 1
    end
    @item_max = @data.size
    return if @item_max == 0
    self.contents = Bitmap.new(width - 32, row_max * 32)
    @item_max.times {|n| draw_item(n) }
  end

  def draw_item(n)
    item = @data[n]
    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
    price = @prices[n]
    if price > 0
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    x = 4 + n % 2 * (288 + 32)
    y = n / 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

  def update_help
    @help_window.set_text(self.item.description)
  end
end

end

class Interpreter
  def buy_price_items(data={})
    KustomPrice.buy_items(data)
  end

  def buy_price_weapons(data={})
    KustomPrice.buy_weapons(data)
  end

  def buy_price_armors(data={})
    KustomPrice.buy_armors(data)
  end

  def sell_price_items(data={})
    KustomPrice.sell_items(data)
  end

  def sell_price_weapons(data={})
    KustomPrice.sell_weapons(data)
  end

  def sell_price_armors(data={})
    KustomPrice.sell_armors(data)
  end
end

class Scene_Map
  def call_shop
    $game_temp.shop_calling = false
    $game_player.straighten
    @custom_shop_id_var ||= KustomPrice::SHOP_ID_VAR
    if $game_variables[@custom_shop_id_var] != 0
      $scene = PriceShopScene.new
    else
      $scene = Scene_Shop.new
    end
  end
end

class PriceShopScene < Scene_Shop
  include KustomPrice
  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_price_shop
  end

  def prepare_goods
    $game_party.compact_bag_items!
    shop_id = find_shop_id
    shop = $game_party.custom_price_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.reset_disabled_items
    @command_window.disable_item(0) if $game_switches[SELL_ONLY_SWITCH]
    @command_window.disable_item(1) if $game_switches[BUY_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 = ShopBuyWindow.new(@goods)
    @buy_window.active = false
    @buy_window.visible = false
    @buy_window.help_window = @help_window
    @sell_window = ShopSellWindow.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)
      if @command_window.disable_current_item?
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      case @command_window.index
      when 0
        open_purchase
      when 1
        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 update_buy
    @status_window.item = @buy_window.item
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      @command_window.active = true
      @dummy_window.visible = true
      @buy_window.active = false
      @buy_window.visible = false
      @status_window.visible = false
      @status_window.item = nil
      @help_window.set_text("")
      return
    elsif Input.trigger?(Input::C)
      @item = @buy_window.item
      price = @buy_window.price
      if @item == nil or $game_party.gold < price
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      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
      if ITEM_MAX == number
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      $game_system.se_play($data_system.decision_se)
      max = price == 0 ? ITEM_MAX : $game_party.gold / price
      max = [max, ITEM_MAX - number].min
      @buy_window.active = false
      @buy_window.visible = false
      @number_window.set(@item, max, price)
      @number_window.active = true
      @number_window.visible = true
    end
  end

  def update_sell
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      @command_window.active = true
      @dummy_window.visible = true
      @sell_window.active = false
      @sell_window.visible = false
      @status_window.item = nil
      @help_window.set_text("")
      return
    elsif Input.trigger?(Input::C)
      @item = @sell_window.item
      @status_window.item = @item
      price = @sell_window.price
      if @item == nil or price == 0
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      $game_system.se_play($data_system.decision_se)
      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
      total = number
      @sell_window.active = false
      @sell_window.visible = false
      @number_window.set(@item, total, price)
      @number_window.active = true
      @number_window.visible = true
      @status_window.visible = true
    end
  end

  def update_number
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      @number_window.active = false
      @number_window.visible = false
      case @command_window.index
      when 0  # buy
        @buy_window.active = true
        @buy_window.visible = true
      when 1  # sell
        @sell_window.active = true
        @sell_window.visible = true
        @status_window.visible = false
      end
      return
    elsif Input.trigger?(Input::C)
      $game_system.se_play($data_system.shop_se)
      @number_window.active = false
      @number_window.visible = false
      case @command_window.index
      when 0  # buy
        price = @buy_window.price
        $game_party.lose_gold(@number_window.number * price)
        case @item
        when RPG::Item
          $game_party.gain_item(@item.id, @number_window.number)
        when RPG::Weapon
          $game_party.gain_weapon(@item.id, @number_window.number)
        when RPG::Armor
          $game_party.gain_armor(@item.id, @number_window.number)
        end
        @gold_window.refresh
        @buy_window.refresh
        @status_window.refresh
        @buy_window.active = true
        @buy_window.visible = true
        return
      when 1  # sell
        price = @sell_window.price
        $game_party.gain_gold(@number_window.number * price)
        case @item
        when RPG::Item
          $game_party.lose_item(@item.id, @number_window.number)
        when RPG::Weapon
          $game_party.lose_weapon(@item.id, @number_window.number)
        when RPG::Armor
          $game_party.lose_armor(@item.id, @number_window.number)
        end
        @gold_window.refresh
        @sell_window.refresh
        @status_window.refresh
        @sell_window.active = true
        @sell_window.visible = true
        @status_window.visible = false
      end
    end
  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_price_shop
    KustomPrice.clear_prices!
    $game_party.compact_bag_items!
    list = @buy_window.shop_goods
    return list.size == @goods.size
    shop_id = find_shop_id
    return if shop_id == 0
    $game_party.setup_price_shop(shop_id, @buy_window.shop_goods)
    $game_variables[SHOP_ID_VAR] = 0
    $game_switches[BUY_ONLY_SWITCH] = false
    $game_switches[SELL_ONLY_SWITCH] = false
  end
end

Terms & Conditions

Free as in Beer beer.
Mention me in your game credits.
You may also add the forum's name and URL there.
That's it! Tongue sticking out