KustomPriceShop XP
#1
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
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9

Maranatha!

The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.

[Image: SP1-Scripter.png]
[Image: SP1-Writer.png]
[Image: SP1-Poet.png]
[Image: SP1-PixelArtist.png]
[Image: SP1-Reporter.png]

My Original Stories (available in English and Spanish)

List of Compiled Binary Executables I have published...
HiddenChest & Roole

Give me a free copy of your completed game if you include at least 3 of my scripts! Laughing + Tongue sticking out

Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Reply




Users browsing this thread: 4 Guest(s)