2 hours ago
(This post was last modified: 2 hours ago by DerVVulfman.)
Aced Shops
Version: 1.0
Initial development began 5-16-2026
Version: 1.0
Initial development began 5-16-2026
Introduction
This script lets one set up shops that may limit interactions. In general it permits these functions:
- Can make a store that only buys from the player or only does sales.
- Can restrict items sold to inddividual stores based on the item IDs
- Can set up a store to have custom prices for certain items
- Can limit the availability of items to a store until restocked.
Script
script
Code:
#==============================================================================
# ** Aced Shops
#------------------------------------------------------------------------------
# by DerVVulfman
# version 1.0 (early uncleaned release)
# 05-17-2026 (mm/dd/yyyy)
# RGSS / RPGMaker XP
#==============================================================================
#
# INTRODUCTION:
#
# This script lets one set up shops that may limit interactions. In general
# it permits these functions:
#
# 1) Can make a store that only buys from the player or only does sales.
# 2) Can restrict items sold to inddividual stores based on the item IDs
# 3) Can set up a store to have custom prices for certain items
# 4) Can limit the availability of items to a store until restocked.
#
# The initial base for this was the Buy Only / Sell Only store by RPG Advocate
# but was so heavily edited, little remains.
#
# SCRIPT CALLS:
#
# Setting a store to buy-only/sell-only:
# > $game_temp.shop_type = value
# * Value is (0)-normal mode, (1)-Buy only, (2)-Sell only
# The value resets to 0 when exiting the shop
#
# Setting a store to recognize shops that accept or refuse items
# > $game_temp.shop_clerk = value
# * Value is used to identify the store that restricts items sold to it
# The value resets to 0 when exiting the shop
#
# Setting a store that sets its own custom prices
# > $game_temp.shop_price = value
# * Value is used to identify the store that has custom prices
# The value resets to 0 when exiting the shop
#
# Setting a store that has limited quantities of goods for sale
# > $game_temp.shop_limit = value
# * Value is used to identify the store that has limited goods
# The value resets to 0 when exiting the shop
#
# Add or reduce items from a store's limited inventory.
# > ace_shop_limit(id=0, item=[0,1], adjust=0)
# * ID: The ID of the shop identified by $game_temp.shop_limit
# * ITEM: The 2-param array identifying the item
# * ADJUST: Defines how much is added or removed from inventory
# A value of 0 removes all items.
# This command can be used to create a new shop rather than using
# the configuration section. Item Arrays are [Type, ID] where the
# type is (0)-Item, (1)-Weapon, or (2)-Armor
#
# Efectively removes limits to items in a store's inventory.
# > ace_shop_delimit(id=0, item=[0,1])
# * ID: The ID of the shop identified by $game_temp.shop_limit
# * ITEM: The 2-param array identifying the item
#
#------------------------------------------------------------------------------
#
# VERSION HISTORY:
#
# beta - 2926-05-16: Demo presentation to Ace_V in Script Requests
# 1.0 - 2026-05-17: Initial Script Release
#
#
#------------------------------------------------------------------------------
#
# COMPATIBILITY:
#
# Performs several rewrites throughout the shop system.
#
#
#==============================================================================
#
# TERMS OF USE:
#
# Free for use, even in commercial games. Only due credit is required.
#
#
#==============================================================================
module Ace_Shops
#----------------------------------------------------------------------------
#-- DO NOT TOUCH THESE LINES ------------------------------------------------
BUYBACK_ACCEPTS, BUYBACK_REFUSAL, PRICE_ADJUSTER, ITEM_LIMIT = {}, {}, {}, {}
#----------------------------------------------------------------------------
# BASIC CUSTOM VALUES
# ===================
# These are general values that may function for any shop regardless of the
# clerk or products sold.
# ---------------------------------------------------------------------------
# DIALOGUE
# --------
# Text that appears in buy only/sell only shop windows
#
WORDS_ONLY_BUY = "You can only buy from this shop."
WORDS_ONLY_SELL = "You can only sell to this shop."
# MAXIMUM QUANTITY
# ----------------
# A value limiting how many items can be purchased or assumed to be held by
# the party. This was added if another script breaks the 99 quantity limit.
#
MAX_BUY_QTY = 99
# STORE LIMIT EFFECTS
# -------------------
# These are text effects that are applied to the individual item(s) that
# have a limited quantity in the store. Setting either to nil removes its
# effect. Entering a LIMIT_TEXT entry result in the item shown as:
# <item> (<text> QTY) eg Potion (Limit: 5)
#
LIMIT_COLOR = Color.new(2,255,255,200)
LIMIT_TEXT = "Limit:"
# STORE ID EFFECTS
# ================
# These are special hash entries for individual store, set before the game
# begins. Each hash's key is the ID of the store, its clerk or etc.
#
# In general, all values are arrays, and the list is a nested array:
# EG: - [ [set 1], [set 2], ... [set 12] ]
# ---------------------------------------------------------------------------
# BUYBACK AND REFUSAL
# -------------------
# REFERS TO: $game_temp.shop_clerk
# ---------------------------------
# The BUYBACK_ACCEPTS hash defines what items are accepted by a store when
# sold back. The BUYBACK_REFUSAL hash defines items the store will not buy.
#
# In general, Items are defined in a 2-parameter array [type, ID] where the
# type may be (0)-Item, (1)-Weapon, or (2)-Armor. Eg. Potion = [0,1]
#
BUYBACK_ACCEPTS[1] = [ [0,1], [1,1], [1,2], [2,21], [2,22]]
BUYBACK_REFUSAL[1] = [ [0,2]]
BUYBACK_REFUSAL[2] = [ [0,1], [1,1], [1,2], [2,21], [2,22]]
# SHOP PRICE ADJUSTER
# -------------------
# REFERS TO: $game_temp.shop_price
# ---------------------------------
# The BUYBACK_ADJUSTER hash defines any custom prices a store believes an
# item should be set. This overrides the default database prices for the
# items.
#
# The items and prices are defined in a 3-parameter array [Type, ID, price]
# where the type may be either (0)-Item, (1)-Weapon, or (2)-Armor. As such
# an entry of [1,1,150] would put a 150 gold value to the bronze sword for
# the store in question
#
PRICE_ADJUSTER[3] = [ [1,4,12000] , [2,1,150] ]
# SHOP PRICE ADJUSTER
# -------------------
# REFERS TO: $game_temp.shop_limit
# ---------------------------------
# ACTUALLY NOT NECESSARY TO SET ANY ENTRY AS IT CAN BE ADDED BY USE OF THE
# ACCOMPANYING EVENT COMMANDS!!!
#
# In general, the ITEM_LIMIT hash arrays define items a store may carry,
# but in limited quantities. The shop must have those items in its normal
# Store Goods list (Shop Processing event) for it to even matter.
#
# The items and prices are defined in a 3-parameter array [Type, ID, price]
# where the type may be either (0)-Item, (1)-Weapon, or (2)-Armor. As such
# an entry of [[0,1],5] would set a 5 max cap on potions in a store until
# it is refilled by a script call.
#
ITEM_LIMIT[6] = [ [[0,1], 5] ]
end
#==============================================================================
# ** Game_Temp
#------------------------------------------------------------------------------
# This class handles temporary data that is not included with save data.
# Refer to "$game_temp" for the instance of this class.
#==============================================================================
class Game_Temp
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :shop_type # Type (0 = normal, 1 = buy, 2 = sell)
attr_accessor :shop_clerk # Individual Shop identification
attr_accessor :shop_price # Defines the shop with custom prices
attr_accessor :shop_limit # Defines the shop with limited goods
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias aceshop_game_temp_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
#
aceshop_game_temp_initialize # Run the original method
@shop_type = 0
@shop_clerk = 0
@shop_price = 0
@shop_limit = 0
#
end
end
#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
# This class handles data surrounding the system. Backround music, etc.
# is managed here as well. Refer to "$game_system" for the instance of
# this class.
#==============================================================================
class Game_System
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :acev_shop_limit # Hash array to contain item limits
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
alias aceshop_game_system_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
#
aceshop_game_system_initialize # Run the original method
initialize_aceshop_limits # Make shop limit hash
#
end
#--------------------------------------------------------------------------
# * Object Initialization : Creating array with shop limits
#--------------------------------------------------------------------------
def initialize_aceshop_limits
#
@acev_shop_limit = {} # Make limit hash array
#
keys = Ace_Shops::ITEM_LIMIT.keys # Get config hash keys
return if keys.empty? # Exit if no config keys
#
for key in keys
list = Ace_Shops::ITEM_LIMIT[key] # Get configed limit list
@acev_shop_limit[key] = list # Set configued limit list
end
#
end
end
#==============================================================================
# ** Window_ShopCommand
#------------------------------------------------------------------------------
# This window is used to choose your business on the shop screen.
#==============================================================================
class Window_ShopCommand < Window_Selectable
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias aceshop_win_shopcmd_initialize initialize
alias aceshop_win_shopcmd_refresh refresh
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
#
initialize_aceshop_prices # Generate shop price list
aceshop_win_shopcmd_initialize # Run the original method
#
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
#
if $game_temp.shop_type != 0 # If a buy/sell shop
return refresh_aceshop_type_options # Use custom options
end
aceshop_win_shopcmd_refresh # Run the original method
#
end
#--------------------------------------------------------------------------
# * Cursor Rectangle Update
#--------------------------------------------------------------------------
def update_cursor_rect
#
return super if $game_temp.shop_type == 0 # Use cursor if default
self.cursor_rect.empty # Hide cursor if custom
#
end
#--------------------------------------------------------------------------
# * Object Initialization : list of shop's custom prices
#--------------------------------------------------------------------------
def initialize_aceshop_prices
#
@prices_item = [] # Create empty arrays
@prices_weapons = [] # For the three types
@prices_armor = [] # of RPG Items
#
key = $game_temp.shop_price # Get shop pricing ID
#
unless Ace_Shops::PRICE_ADJUSTER.has_key?(key) # If key not defined
return # Exit the method
end
#
prices = Ace_Shops::PRICE_ADJUSTER[key] # Get prices for the shop
#
for price in prices # Sort through shop prices
type = price[0] # Get item type
id = price[1] # Get item ID
cost = price[2] # Get item cost
value = [id,cost] # Define ID/Cost array
case type # Branch on type
when 1 ; @prices_weapons.push(value) # Push ID/COST into weaps
when 2 ; @prices_armor.push(value) # Push ID/COST into armor
else ; @prices_item.push(value) # Push ID/COST into items
end
#
end
#
end
#--------------------------------------------------------------------------
# * Get shop's custom price of item
# item : Item
#--------------------------------------------------------------------------
def get_aceshop_prices(item)
#
id, cost = item.id, item.price # Get item ID and price
#
case item # Branch on item type
when RPG::Item ; prices = @prices_item # Get shop's item prices
when RPG::Weapon ; prices = @prices_weapons # Get shop's weapon prices
when RPG::Armor ; prices = @prices_armor # Get shop's armor prices
end
#
return cost if prices == [] # Use cost if nor prices
for item in prices # Sort through prices
cost = item[1] if item[0] == id # Replace if custom found
end
return cost # Exit with price
#
end
#--------------------------------------------------------------------------
# * Refresh customized buy/sell options window
#--------------------------------------------------------------------------
def refresh_aceshop_type_options
#
if $game_temp.shop_type == 1 # If a buy only shop
text = Ace_Shops::WORDS_ONLY_BUY # set message
else # Otherwise
text = Ace_Shops::WORDS_ONLY_SELL # set message
end
#
self.contents.draw_text(4, 0, 324, 32, text) # Show the message
self.index = -1 # Set the index position
update_cursor_rect # Update cursor rect
#
end
end
#==============================================================================
# ** Window_ShopBuy
#------------------------------------------------------------------------------
# This window displays buyable goods on the shop screen.
#==============================================================================
class Window_ShopBuy < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
alias aceshop_window_buy_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
# shop_goods : goods
#--------------------------------------------------------------------------
def initialize(shop_goods)
#
initialize_aceshop_prices # Generate shop price list
aceshop_window_buy_initialize(shop_goods) # Run the original method
#
end
#--------------------------------------------------------------------------
# * Object Initialization : list of shop's custom prices
#--------------------------------------------------------------------------
def initialize_aceshop_prices
#
@prices_item = [] # Create empty arrays
@prices_weapons = [] # For the three types
@prices_armor = [] # of RPG Items
#
key = $game_temp.shop_price # Get shop pricing ID
#
unless Ace_Shops::PRICE_ADJUSTER.has_key?(key) # If key not defined
return # Exit the method
end
#
prices = Ace_Shops::PRICE_ADJUSTER[key] # Get prices for the shop
#
for price in prices # Sort through shop prices
type = price[0] # Get item type
id = price[1] # Get item ID
cost = price[2] # Get item cost
value = [id,cost] # Define ID/Cost array
case type # Branch on type
when 1 ; @prices_weapons.push(value) # Push ID/COST into weaps
when 2 ; @prices_armor.push(value) # Push ID/COST into armor
else ; @prices_item.push(value) # Push ID/COST into items
end
#
end
#
end
#--------------------------------------------------------------------------
# * Get shop's custom price of item
# item : Item
#--------------------------------------------------------------------------
def get_aceshop_prices(item)
#
id, cost = item.id, item.price # Get item ID and price
#
case item # Branch on item type
when RPG::Item ; prices = @prices_item # Get shop's item prices
when RPG::Weapon ; prices = @prices_weapons # Get shop's weapon prices
when RPG::Armor ; prices = @prices_armor # Get shop's armor prices
end
#
return cost if prices == [] # Use cost if nor prices
for item in prices # Sort through prices
cost = item[1] if item[0] == id # Replace if custom found
end
return cost # Exit with price
#
end
#--------------------------------------------------------------------------
# * Draw Item
# index : item number
#--------------------------------------------------------------------------
def draw_item(index)
#
item = @data[index] # Get the current item
price = get_aceshop_prices(item) # Get price
max_qty = Ace_Shops::MAX_BUY_QTY # Set max quantity(99)
gold = $game_party.gold # Get party gold
limit = draw_item_get_limit(item) # Get item limit
limit_color = Ace_Shops::LIMIT_COLOR # Get item limit color
name = draw_item_get_name(item, limit) # Get item name
color_nil = false
color_nil = true if Ace_Shops::LIMIT_COLOR.nil?
#
case item # Branch on item type
when RPG::Item # If an ITEM
number = $game_party.item_number(item.id) # Get item quantity
when RPG::Weapon # If an WEAPON
number = $game_party.weapon_number(item.id) # Get weapon quantity
when RPG::Armor # If ARMOR
number = $game_party.armor_number(item.id) # Get armor quantity
end
#
if price <= gold and number < max_qty # Enough gold & not maxed?
if limit >= 0 && !limit_color.nil?
self.contents.font.color = limit_color # Set normal text
else
self.contents.font.color = normal_color # Set normal text
end
else # Otherwise
self.contents.font.color = disabled_color # Set disabled text
end
#
# The typical rest of the method
x = 4
y = index * 32
rect = Rect.new(x, y, self.width - 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)
#
# Use custom name (not item.name)
self.contents.draw_text(x + 28, y, 212, 32, name, 0)
#
# Use custom price (not item.price)
self.contents.draw_text(x + 240, y, 88, 32, price.to_s, 2)
#
end
#--------------------------------------------------------------------------
# * Get quantity limit to drawn Item
# item : Item
#--------------------------------------------------------------------------
def draw_item_get_limit(item)
#
key = $game_temp.shop_limit # Get shop limit ID
#
unless $game_system.acev_shop_limit.has_key?(key) # If key not defined
return -1 # Exit the method
end
#
list = $game_system.acev_shop_limit[key] # Get store limit list
#
case item # Branch on type
when RPG::Item ; type = 0 # Set type to 0
when RPG::Weapon ; type = 1 # Set type to 1
when RPG::Armor ; type = 2 # Set type to 2
end
#
qty = -1 # Assume 0 limit
for set in list # Loop through items
next unless set[0][0] == type # Skip if not right type
qty = set[1] if set[0][1] == item.id # Get limit type/id found
end
#
return qty # Exit with limit value
#
end
#--------------------------------------------------------------------------
# * Get quantity name
# item : Item
#--------------------------------------------------------------------------
def draw_item_get_name(item, limit)
#
name = item.name
return name if Ace_Shops::LIMIT_TEXT.nil?
return name if limit < 0
#
name += " (" + Ace_Shops::LIMIT_TEXT + " " + limit.to_s + ")"
return name
#
end
end
#==============================================================================
# ** Window_ShopSell
#------------------------------------------------------------------------------
# This window displays items in possession for selling on the shop screen.
#==============================================================================
class Window_ShopSell < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
alias aceshop_window_sell_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
#
initialize_aceshop_arrays # Make arrays of accepteds
initialize_aceshop_prices # Generate shop price list
aceshop_window_sell_initialize # Run the original method
#
end
#--------------------------------------------------------------------------
# * Object Initialization : generating required arrays of limited items
#--------------------------------------------------------------------------
def initialize_aceshop_arrays
#
@accept_item = []
@accept_weapon = []
@accept_armor = []
@refuse_item = []
@refuse_weapon = []
@refuse_armor = []
return if $game_temp.shop_clerk == 0 # Exit if no banned items
#
initialize_aceshop_accepts # Make list of accepted
initialize_aceshop_refuses # Make list of banned
initialize_aceshop_validity # Check list validity
#
end
#--------------------------------------------------------------------------
# * Object Initialization : generating content of permitted item types
#--------------------------------------------------------------------------
def initialize_aceshop_accepts
#
key = $game_temp.shop_clerk # Get clerk ID
unless Ace_Shops::BUYBACK_ACCEPTS.has_key?(key) # If no setting exists
return # Exit method
end
#
for item in Ace_Shops::BUYBACK_ACCEPTS[key] # Sort configured items
@accept_item.push(item[1]) if item[0] == 0 # Push into list if item
@accept_weapon.push(item[1]) if item[0] == 1 # Push into list if weapon
@accept_armor.push(item[1]) if item[0] == 2 # Push into list if armor
end
#
end
#--------------------------------------------------------------------------
# * Object Initialization : generating content of refused item types
#--------------------------------------------------------------------------
def initialize_aceshop_refuses
#
key = $game_temp.shop_clerk # Get clerk ID
unless Ace_Shops::BUYBACK_REFUSAL.has_key?(key) # If no setting exists
return # Exit method
end
#
for item in Ace_Shops::BUYBACK_REFUSAL[key] # Sort configured items
@refuse_item.push(item[1]) if item[0] == 0 # Push into list if item
@refuse_weapon.push(item[1]) if item[0] == 1 # Push into list if weapon
@refuse_armor.push(item[1]) if item[0] == 2 # Push into list if armor
end
#
end
#--------------------------------------------------------------------------
# * Object Initialization : validating content between array data
#--------------------------------------------------------------------------
def initialize_aceshop_validity
#
# Generate warning messages if list conflicts exist
if @accept_item != [] && @refuse_item != []
p "Warning: Cannot have items in both accept and refusal arrays"
end
if @accept_weapon != [] && @refuse_weapon != []
p "Warning: Cannot have weapons in both accept and refusal arrays"
end
if @accept_armor != [] && @refuse_armor != []
p "Warning: Cannot have armors in both accept and refusal arrays"
end
#
# If Items are accepted, set refused items to -1 (to fail ban test)
if @accept_item != [] && @refuse_item == []
@refuse_item = [-1]
# If Items are refused, set accapted items to -1 (to pass accept test)
elsif @accept_item == [] && @refuse_item != []
@accept_item = [-1]
# If neither arrays for items are not filled, set both arrays to fully pass
else
@refuse_item = [-1]
@accept_item = [-1]
end
#
# Determine which array has content, and flag alternate as always psss
if @accept_weapon != [] && @refuse_weapon == []
@refuse_weapon = [-1]
elsif @accept_weapon == [] && @refuse_weapon != []
@accept_weapon = [-1]
else
@refuse_weapon = [-1]
@accept_weapon = [-1]
end
#
# Determine which array has content, and flag alternate as always psss
if @accept_armor != [] && @refuse_armor == []
@refuse_armor = [-1]
elsif @accept_armor == [] && @refuse_armor != []
@accept_armor = [-1]
else
@refuse_armor = [-1]
@accept_armor = [-1]
end
#
end
#--------------------------------------------------------------------------
# * Object Initialization : list of shop's custom prices
#--------------------------------------------------------------------------
def initialize_aceshop_prices
#
@prices_item = [] # Create empty arrays
@prices_weapons = [] # For the three types
@prices_armor = [] # of RPG Items
#
key = $game_temp.shop_price # Get shop pricing ID
#
unless Ace_Shops::PRICE_ADJUSTER.has_key?(key) # If key not defined
return # Exit the method
end
#
prices = Ace_Shops::PRICE_ADJUSTER[key] # Get prices for the shop
#
for price in prices # Sort through shop prices
type = price[0] # Get item type
id = price[1] # Get item ID
cost = price[2] # Get item cost
value = [id,cost] # Define ID/Cost array
case type # Branch on type
when 1 ; @prices_weapons.push(value) # Push ID/COST into weaps
when 2 ; @prices_armor.push(value) # Push ID/COST into armor
else ; @prices_item.push(value) # Push ID/COST into items
end
#
end
#
end
#--------------------------------------------------------------------------
# * Get shop's custom price of item
# item : Item
#--------------------------------------------------------------------------
def get_aceshop_prices(item)
#
id, cost = item.id, item.price # Get item ID and price
#
case item # Branch on item type
when RPG::Item ; prices = @prices_item # Get shop's item prices
when RPG::Weapon ; prices = @prices_weapons # Get shop's weapon prices
when RPG::Armor ; prices = @prices_armor # Get shop's armor prices
end
#
return cost if prices == [] # Use cost if nor prices
for item in prices # Sort through prices
cost = item[1] if item[0] == id # Replace if custom found
end
return cost # Exit with price
#
end
#--------------------------------------------------------------------------
# * Draw Item
# index : item number
#--------------------------------------------------------------------------
def draw_item(index)
#
item = @data[index] # Get the current item
price = get_aceshop_prices(item) # Get price
#
case item # Branch on item type
when RPG::Item # If an ITEM
number = $game_party.item_number(item.id) # Get item quantity
when RPG::Weapon # If an WEAPON
number = $game_party.weapon_number(item.id) # Get weapon quantity
when RPG::Armor # If ARMOR
number = $game_party.armor_number(item.id) # Get armor quantity
end
#
if price > 0 # If a valid price
self.contents.font.color = normal_color # Set normal text
else # Otherwise
self.contents.font.color = disabled_color # Set disabled
end
#
# The typical rest of the method
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
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
#
if self.contents != nil
self.contents.dispose
self.contents = nil
end
#
@data = [] # Create data array
#
refresh_items # Add items into data
refresh_weapons # Add weapons into data
refresh_armors # Add armor into data
refresh_list # Display list
#
end
#--------------------------------------------------------------------------
# * Refresh : item list compiled
#--------------------------------------------------------------------------
def refresh_items
#
for i in 1...$data_items.size # Cycle database items
#
next unless refresh_aceshop_permit?(i, 0) # Skip unless permitted
next if refresh_aceshop_refuse?(i, 0) # Skip if banned
next unless $game_party.item_number(i) > 0 # Skip if no party qty
@data.push($data_items[i]) # Add party item
#
end
#
end
#--------------------------------------------------------------------------
# * Refresh : weapon list compiled
#--------------------------------------------------------------------------
def refresh_weapons
#
for i in 1...$data_weapons.size # Cycle database weapons
#
next unless refresh_aceshop_permit?(i, 1) # Skip unless permitted
next if refresh_aceshop_refuse?(i, 1) # Skip if banned
next unless $game_party.weapon_number(i) > 0 # Skip if no party qty
@data.push($data_weapons[i]) # Add party item
#
end
#
end
#--------------------------------------------------------------------------
# * Refresh : armor list compiled
#--------------------------------------------------------------------------
def refresh_armors
#
for i in 1...$data_armors.size # Cycle database armor
#
next unless refresh_aceshop_permit?(i, 2) # Skip unless permitted
next if refresh_aceshop_refuse?(i, 2) # Skip if banned
next unless $game_party.armor_number(i) > 0 # Skip if no party qty
@data.push($data_armors[i]) # Add party item
#
end
#
end
#--------------------------------------------------------------------------
# * Refresh : generate list
#--------------------------------------------------------------------------
def refresh_list
#
# If item count is not 0, make a bitmap and draw all items
@item_max = @data.size
#
# Exit if no data to show
return unless @item_max > 0
#
# Create display area and output list
self.contents = Bitmap.new(width - 32, row_max * 32)
for i in 0...@item_max
draw_item(i)
end
#
end
#--------------------------------------------------------------------------
# * Refresh : testing item if it is allowed to be shown
# id : item_ID
# type : RPG Type: 0-item, 1-weapon, 2-armor
#--------------------------------------------------------------------------
def refresh_aceshop_permit?(id, type)
#
# Test passes as normal
return true if $game_temp.shop_clerk == 0
#
# Assume failure (do not permit)
effective = false
#
# Branch on data type
case type
when 1 ; # Test for item ID or if fully allowed
effective = true if @accept_weapon.include?(id)
effective = true if @accept_weapon == [-1]
effective = false if @accept_weapon == []
when 2 ; # Test for item ID or if fully allowed
effective = true if @accept_armor.include?(id)
effective = true if @accept_armor == [-1]
effective = false if @accept_armor == []
else ; # Test for item ID or if fully allowed
effective = true if @accept_item.include?(id)
effective = true if @accept_item == [-1]
effective = false if @accept_item == []
end
#
# Exit with result
return effective
#
end
#--------------------------------------------------------------------------
# * Refresh : testing item if it is barred from being shown
# id : item_ID
# type : RPG Type: 0-item, 1-weapon, 2-armor
#--------------------------------------------------------------------------
def refresh_aceshop_refuse?(id, type)
#
# Test fails as normal (
return false if $game_temp.shop_clerk == 0
#
# Assume failure (permit)
effective = false
#
# Branch on data type
case type
when 1 ; # Test for item ID or if fully allowed
effective = true if @refuse_weapon.include?(id)
effective = false if @refuse_weapon == [-1]
when 2 ; # Test for item ID or if fully allowed
effective = true if @refuse_armor.include?(id)
effective = false if @refuse_armor == [-1]
else ; # Test for item ID or if fully allowed
effective = true if @refuse_item.include?(id)
effective = false if @refuse_item == [-1]
end
#
# Exit with result
return effective
#
end
end
#==============================================================================
# ** Interpreter
#------------------------------------------------------------------------------
# This interpreter runs event commands. This class is used within the
# Game_System class and the Game_Event class.
#==============================================================================
class Interpreter
#--------------------------------------------------------------------------
# * Adjust shop limit to individual item
# id : store id ($game_temp.shop_limit)
# item : Item ID
# adjust : increase or decrease in custom quantity
#--------------------------------------------------------------------------
def ace_shop_limit(id=0, item=[0,1], adjust=0)
#
# Ensure no invalid entries
return if id.nil? # Exit if nil
return if item.nil? # Exit if nil
return if adjust.nil? # Exit if nil
return unless id.is_a?(Numeric) # Exit if not numeric
return unless item.is_a?(Array) # Exit if not an array
return unless adjust.is_a?(Numeric) # Exit if not numeric
return if id <= 0 # Exit if invalid value
return if item.empty? # Exit if empty item
return unless item.size == 2 # Exit unless 2-param
test = item[0] # Get item type
return unless [0,1,2].include?(test) # Exit if incorrect type
#
# Test the storage array
test = $game_system.acev_shop_limit.has_key?(id) # Test for the shop
if !test # If no shop entry
set_list = [[item, adjust]] # Create the set list
$game_system.acev_shop_limit[id] = set_list # Create an entry
return # And Exit
end
#
list = $game_system.acev_shop_limit[id] # Get store limit list
#
# Adjust for an existing shop
test = false # Assume item not found
for set in list # Loop through items
if set[0] == item # If item is found
test = true # Show item found
old_qty = set[1] # Get current limit
old_qty += adjust # Adjust the limit
old_qty = 0 if old_qty < 0 # Ensure no less than 0
old_qty = 0 if adjust == 0 # Set to 0 if adjust 0
set[1] = old_qty # Reapply to the set
end
end
#
if test == false # If the item not found
list.push([item, adjust]) # Creeate item limit set
end
#
$game_system.acev_shop_limit[id] = list # Replace in the hash
#
end
#--------------------------------------------------------------------------
# * Remove shop limit to individual item
# id : store id ($game_temp.shop_limit)
# item : Item ID
#--------------------------------------------------------------------------
def ace_shop_delimit(id=0, item=[0,1])
#
# Ensure no invalid entries
return if id.nil? # Exit if nil
return if item.nil? # Exit if nil
return unless id.is_a?(Numeric) # Exit if not numeric
return unless item.is_a?(Array) # Exit if not an array
return if id <= 0 # Exit if invalid value
return if item.empty? # Exit if empty item
return unless item.size == 2 # Exit unless 2-param
test = item[0] # Get item type
return unless [0,1,2].include?(test) # Exit if incorrect type
#
# Test the storage array
test = $game_system.acev_shop_limit.has_key?(id) # Test for the shop
return if !test # Exit if no shop entry
#
new_list = [] # Create new array
for set in list # Loop through items
next if set[0] == item # Skip flagged item
new_list.push(set) # Add to the new array
end
#
$game_system.acev_shop_limit[id] = list # Replace in the hash
#
end
end
#==============================================================================
# ** Scene_Shop
#------------------------------------------------------------------------------
# This class performs shop screen processing.
#==============================================================================
class Scene_Shop
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
#
main_windows
main_windows_type_1
main_windows_type_2
#
Graphics.transition
loop do
Graphics.update
Input.update
update
break if $scene != self
end
Graphics.freeze
#
main_dispose
$game_temp.shop_type = 0
$game_temp.shop_clerk = 0
$game_temp.shop_price = 0
$game_temp.shop_limit = 0
#
end
#--------------------------------------------------------------------------
# * Main Processing : creating the windows
#--------------------------------------------------------------------------
def main_windows
#
@help_window = Window_Help.new
@command_window = Window_ShopCommand.new
@dummy_window = Window_Base.new(0, 128, 640, 352)
#
@gold_window = Window_Gold.new
@gold_window.x = 480
@gold_window.y = 64
#
@buy_window = Window_ShopBuy.new($game_temp.shop_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
#--------------------------------------------------------------------------
# * Main Processing : Adjusting windows for type 1 shop (buy only)
#--------------------------------------------------------------------------
def main_windows_type_1
#
return unless $game_temp.shop_type == 1
#
@command_window.index = 0
@command_window.active = false
@dummy_window.visible = false
#
@buy_window.active = true
@buy_window.visible = true
@buy_window.refresh
#
@status_window.visible = true
#
end
#--------------------------------------------------------------------------
# * Main Processing : Adjusting windows for type 2 shop (sell only)
#--------------------------------------------------------------------------
def main_windows_type_2
#
return unless $game_temp.shop_type == 2
#
@command_window.index = 1
@command_window.active = false
@dummy_window.visible = false
#
@sell_window.active = true
@sell_window.visible = true
@sell_window.refresh
#
end
#--------------------------------------------------------------------------
# * Main Processing : final window refresh and disposal
#--------------------------------------------------------------------------
def main_dispose
#
@status_window.item = nil
@status_window.refresh
@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
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
#
update_windows
update_on_active
#
end
#--------------------------------------------------------------------------
# * Frame Update (when updating windows regardless of state)
#--------------------------------------------------------------------------
def update_windows
#
@help_window.update
@command_window.update
@gold_window.update
@dummy_window.update
@buy_window.update
@sell_window.update
@number_window.update
@status_window.update
#
end
#--------------------------------------------------------------------------
# * Frame Update (when updating only active windows)
#--------------------------------------------------------------------------
def update_on_active
#
return update_command if @command_window.active
return update_buy if @buy_window.active
return update_sell if @sell_window.active
return update_number if @number_window.active
#
end
#--------------------------------------------------------------------------
# * Frame Update (when command window is active)
#--------------------------------------------------------------------------
def update_command
#
return if update_command_cancel?
update_command_decision?
#
end
#--------------------------------------------------------------------------
# * Frame Update (when testing for shop process cancellation)
#--------------------------------------------------------------------------
def update_command_cancel?
#
return false unless Input.trigger?(Input::B)
#
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when testing for shop process decision)
#--------------------------------------------------------------------------
def update_command_decision?
#
return false unless Input.trigger?(Input::C)
#
case @command_window.index
when 0 ; update_command_buy
when 1 ; update_command_sell
else ; update_command_exit
end
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when confirming a buy only shop)
#--------------------------------------------------------------------------
def update_command_buy
#
$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
#--------------------------------------------------------------------------
# * Frame Update (when confirming a sell only shop)
#--------------------------------------------------------------------------
def update_command_sell
#
$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
#--------------------------------------------------------------------------
# * Frame Update (when confirming shop exit)
#--------------------------------------------------------------------------
def update_command_exit
#
$game_system.se_play($data_system.decision_se)
$scene = Scene_Map.new
#
end
#--------------------------------------------------------------------------
# * Frame Update (when buy window is active)
#--------------------------------------------------------------------------
def update_buy
#
# Set status window item
@status_window.item = @buy_window.item
return if update_buy_cancel?
update_buy_decision?
#
end
#--------------------------------------------------------------------------
# * Frame Update (when cancelling within the buy window)
#--------------------------------------------------------------------------
def update_buy_cancel?
#
# Exit false unless B button was pressed
return false unless Input.trigger?(Input::B)
#
if $game_temp.shop_type == 1
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return true
end
#
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
#
# Change windows to initial mode
@command_window.active = true
@dummy_window.visible = true
@buy_window.active = false
@buy_window.visible = false
@status_window.visible = false
@status_window.item = nil
# Erase help text
@help_window.set_text("")
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when deciding within the buy window)
#--------------------------------------------------------------------------
def update_buy_decision?
#
# Exit false unless C button was pressed
return false unless Input.trigger?(Input::C)
#
# Get item
@item = @buy_window.item
id = @item.id
price = @command_window.get_aceshop_prices(@item)
#
# If item is invalid, or price is higher than money possessed
if @item.nil? or price > $game_party.gold
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return true
end
#
# Get items in possession count
case @item
when RPG::Item ; number = $game_party.item_number(id)
when RPG::Weapon ; number = $game_party.weapon_number(id)
when RPG::Armor ; number = $game_party.armor_number(id)
end
#
max_qty = Ace_Shops::MAX_BUY_QTY
#
# If 99 items are already in possession
if number == max_qty
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return true
end
#
# Play decision SE
$game_system.se_play($data_system.decision_se)
#
# Calculate maximum amount possible to buy
max = update_buy_maximum(@item, price, max_qty, number)
#
# Change windows to quantity input mode
@buy_window.active = false
@buy_window.visible = false
@number_window.set(@item, max, price)
@number_window.active = true
@number_window.visible = true
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when deciding within the buy maximum)
#--------------------------------------------------------------------------
def update_buy_maximum(item, price, max_qty, number)
#
max = price == 0 ? max_qty : $game_party.gold / price
max = [max, max_qty - number].min
#
return max if $game_temp.shop_limit == 0 # Exit if no shop set
id = $game_temp.shop_limit # Get shop ID
test = $game_system.acev_shop_limit.has_key?(id) # Test hash for shop ID
return max if !test # Exit with max if no shop
#
list = $game_system.acev_shop_limit[id] # Get store limit list
#
case item # Branch on type
when RPG::Item ; type = 0 # Set type to 0
when RPG::Weapon ; type = 1 # Set type to 1
when RPG::Armor ; type = 2 # Set type to 2
end
#
qty = 0 # Assume 0 limit
for set in list # Loop through items
next unless set[0][0] == type # Skip if not right type
qty = set[1] if set[0][1] == item.id # Get limit type/id found
end
#return max if qty == 0 # Use max if no limit
max = (qty < max) ? qty : max # Use lesser of limits
#
end
#--------------------------------------------------------------------------
# * Frame Update (when sell window is active)
#--------------------------------------------------------------------------
def update_sell
#
return if update_sell_cancel?
update_sell_decision?
#
end
#--------------------------------------------------------------------------
# * Frame Update (when cancelling within the sell window)
#--------------------------------------------------------------------------
def update_sell_cancel?
#
# Exit false unless B button was pressed
return false unless Input.trigger?(Input::B)
#
if $game_temp.shop_type == 2
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return true
end
#
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
#
# Change windows to initial mode
@command_window.active = true
@dummy_window.visible = true
@sell_window.active = false
@sell_window.visible = false
@status_window.item = nil
# Erase help text
@help_window.set_text("")
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when deciding within the sell window)
#--------------------------------------------------------------------------
def update_sell_decision?
#
# Exit false unless C button was pressed
return false unless Input.trigger?(Input::C)
#
# Get item
@item = @sell_window.item
#
price = @command_window.get_aceshop_prices(@item)
#
# Set status window item
@status_window.item = @item
#
# If item is invalid, or item price is 0 (unable to sell)
if @item.nil? or price == 0
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return true
end
#
# Play decision SE
$game_system.se_play($data_system.decision_se)
#
# Get items in possession count
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
#
# Maximum quanitity to sell = number of items in possession
max = number
#
# Change windows to quantity input mode
@sell_window.active = false
@sell_window.visible = false
@number_window.set(@item, max, price / 2)
@number_window.active = true
@number_window.visible = true
@status_window.visible = true
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when quantity input window is active)
#--------------------------------------------------------------------------
def update_number
#
return if update_number_cancel?
update_number_decision?
#
end
#--------------------------------------------------------------------------
# * Frame Update (when cancelling within the quantity input window)
#--------------------------------------------------------------------------
def update_number_cancel?
#
# If B button was pressed
return false unless Input.trigger?(Input::B)
#
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
#
# Set quantity input window to inactive / invisible
@number_window.active = false
@number_window.visible = false
#
# Branch by command window cursor position
case @command_window.index
when 0 # buy
# Change windows to buy mode
@buy_window.active = true
@buy_window.visible = true
when 1 # sell
# Change windows to sell mode
@sell_window.active = true
@sell_window.visible = true
@status_window.visible = false
end
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when deciding within the quantity input window)
#--------------------------------------------------------------------------
def update_number_decision?
#
# If C button was pressed
return false unless Input.trigger?(Input::C)
#
# Play shop SE
$game_system.se_play($data_system.shop_se)
#
# Set quantity input window to inactive and hidden
@number_window.active = false
@number_window.visible = false
#
# Branch by command window cursor position
case @command_window.index
when 0 ; update_number_buy
when 1 ; update_number_sell
end
return true
#
end
#--------------------------------------------------------------------------
# * Frame Update (when buying items within the quantity input window)
#--------------------------------------------------------------------------
def update_number_buy
#
# Buy item and quantity
id = @item.id
price = @command_window.get_aceshop_prices(@item)
qty = @number_window.number
#
# Buy process
$game_party.lose_gold(qty * price)
#
# Branch on item type and add item
case @item
when RPG::Item ; $game_party.gain_item(id, qty)
when RPG::Weapon ; $game_party.gain_weapon(id, qty)
when RPG::Armor ; $game_party.gain_armor(id, qty)
end
#
update_number_buy_limit(@item, qty)
#
# Refresh each window
@gold_window.refresh
@buy_window.refresh
@status_window.refresh
#
# Change windows to buy mode
@buy_window.active = true
@buy_window.visible = true
#
end
#--------------------------------------------------------------------------
# * Adjust shop limit to individual item
# item : Item
# quantity : numeer to reduce
#--------------------------------------------------------------------------
def update_number_buy_limit(item, quantity)
#
return if $game_temp.shop_limit == 0 # Exit if no limit shop
#
id = $game_temp.shop_limit
test = $game_system.acev_shop_limit.has_key?(id) # Test for the shop
return if !test # Exit if no shop entry
#
case item # Branch on item type
when RPG::Item ; type = 0 # Define the type value
when RPG::Weapon ; type = 1 # For use within the
when RPG::Armor ; type = 2 # following test array
end
test = [type, item.id] # create test array
#
list = $game_system.acev_shop_limit[id] # Get store limit list
#
for set in list # Loop through items
next unless set[0] == test # skip if not the item
old_qty = set[1] # Get current limit
old_qty -= quantity # Reduce by sold quantity
set[1] = old_qty
end
# #
# # Now cleanup to remove 0 limiter
# new_list = [] # Make an empty array
# for set in list # Sort through items
# new_list.push(set) if set[1] != 0 # Add to array if not 0
# end
# list = new_list # Replace/use new array
#
$game_system.acev_shop_limit[id] = list # Replace in the hash
#
end
#--------------------------------------------------------------------------
# * Frame Update (when selling items within the quantity input window)
#--------------------------------------------------------------------------
def update_number_sell
#
# Sell item and quantity
id = @item.id
price = @command_window.get_aceshop_prices(@item)
qty = @number_window.number
#
# Sell process
$game_party.gain_gold(qty * (price / 2))
#
# Branch on item type and lose item
case @item
when RPG::Item ; $game_party.lose_item(id, qty)
when RPG::Weapon ; $game_party.lose_weapon(id, qty)
when RPG::Armor ; $game_party.lose_armor(id, qty)
end
#
# Refresh each window
@gold_window.refresh
@sell_window.refresh
@status_window.refresh
#
# Change windows to sell mode
@sell_window.active = true
@sell_window.visible = true
@status_window.visible = false
#
end
endInstructions
On this release, I was barebones on instructions. I will return later with more instructions.
FAQ
This was per a request by Ace_V, said request and development found here:
https://www.save-point.org/thread-13478-lastpost.html
While development began initially with RPG Advocate's Buy Only/Sell-Only script, little of it even remains.
Compatibility
Performs several rewrites throughout the shop system.
Terms and Conditions
Free for use, even in commercial games. Only due credit is required.
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)
Above are clickable links

![[Image: QrnbKlx.jpg]](https://i.imgur.com/QrnbKlx.jpg)
![[Image: sGz1ErF.png]](https://i.imgur.com/sGz1ErF.png)
![[Image: liM4ikn.png]](https://i.imgur.com/liM4ikn.png)
![[Image: fdzKgZA.png]](https://i.imgur.com/fdzKgZA.png)
![[Image: sj0H81z.png]](https://i.imgur.com/sj0H81z.png)
![[Image: QL7oRau.png]](https://i.imgur.com/QL7oRau.png)
![[Image: uSqjY09.png]](https://i.imgur.com/uSqjY09.png)
![[Image: GAA3qE9.png]](https://i.imgur.com/GAA3qE9.png)
![[Image: 2Hmnx1G.png]](https://i.imgur.com/2Hmnx1G.png)
![[Image: BwtNdKw.png%5B]](https://i.imgur.com/BwtNdKw.png%5B)