Aced Shops 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
#--------------------------------------------------------------------------
# * 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 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
end
Instructions
On this release, I was barebones on instructions. I will return later with more instructions.