#------------------------------------------------------------------------------#
# RMX-OS Player Shops #
# by Wizered67 #
# V 0.89 #
# All errors should be reported at www.chaos-project.com. #
#------------------------------------------------------------------------------#
module PlayerShopConfig
SHOP_COST = 500
end
#==============================================================================
# module RMXOS
#==============================================================================
module RMXOS
#============================================================================
# module Documentation
#============================================================================
module Documentation
PARAMETERS['shops'] = 'none'
PARAMETERS['makeshop'] = 'SHOPNAME'
PARAMETERS['editshop'] = 'SHOPID'
PARAMETERS['buy'] = 'SHOPID'
DESCRIPTIONS['shops'] = 'Displays a list of all shops on the same map.'
DESCRIPTIONS['makeshop'] = "Creates a new shop on the current map. Costs #{PlayerShopConfig::SHOP_COST} gold."
DESCRIPTIONS['editshop'] = 'Edits the shop with the specified id.'
DESCRIPTIONS['buy'] = 'Opens the shop with the specified id. Only 1 player can be using a shop at a time.'
end
#============================================================================
# module Data
#============================================================================
module Data
PlayerShopsReceivedMoney = 'Received AMOUNT Gold for purchases made in your shop.'
NewShopCreated = "Spent #{PlayerShopConfig::SHOP_COST} gold and created a new shop with id: ID. Add items with /editshop SHOPID"
InvalidItemShop = 'Invalid item or shop has been selected.'
NotEnoughMoney = "Not enough money to make a shop. It costs #{PlayerShopConfig::SHOP_COST} gold."
end
#============================================================================
# Network
#============================================================================
class Network
def sell_item(price)
if $game_temp.player_shop_sell_item == nil || $game_temp.player_shop_sell_selected == 0
self.add_error(RMXOS::Data::InvalidItemShop)
return
end
type = 0
case $game_temp.player_shop_sell_item
when RPG::Item
$game_party.lose_item($game_temp.player_shop_sell_item.id, $game_temp.player_shop_sell_amount)
type = 0
when RPG::Weapon
$game_party.lose_weapon($game_temp.player_shop_sell_item.id, $game_temp.player_shop_sell_amount)
type = 1
when RPG::Armor
$game_party.lose_armor($game_temp.player_shop_sell_item.id, $game_temp.player_shop_sell_amount)
type = 2
end
shop = $game_temp.player_shop_sell_selected
item = $game_temp.player_shop_sell_item.id
amount = $game_temp.player_shop_sell_amount
self.send('SCD', shop, item, amount, price, type)
end
alias check_game_player_shops_alias check_game
def check_game(message)
case message
when /\ARMPS\t(.+)/
amount = $1
self.add_message(0, RMXOS::Data::PlayerShopsReceivedMoney.sub('AMOUNT',
amount), RMXOS::Data::ColorOk)
$game_party.gain_gold(amount.to_i)
return true
when /\ANSI\t(.+)/
id = $1.to_i
self.add_message(0, RMXOS::Data::NewShopCreated.sub('ID',
id.to_s), RMXOS::Data::ColorOk)
return true
when /\ALSSD\t(.+)/
$game_temp.player_shop_buy_items = eval($1)
$game_temp.player_shop_owner = $game_temp.player_shop_buy_items[0]
$game_temp.player_shop_name = $game_temp.player_shop_buy_items[4]
$scene = Scene_PlayerShopBuy.new
return true
when /\AEIS\Z/ #invalid shop selected (sell)
$game_temp.player_shop_sell_selected = 0
return true
when /\AEISB\Z/ #invalid shop selected (buy)
$game_temp.player_shop_buy_selected = 0
return true
when /\AOESC\t(.+)\t(.+)/ #open edit shop screen
$game_temp.player_shop_owner = $1
$game_temp.player_shop_name = $2
$scene = Scene_PlayerShopSell.new
return true
end
return check_game_player_shops_alias(message)
end
alias check_normal_commands_player_shops_alias check_normal_commands
def check_normal_commands(message)
case message
when /\A\/shops\Z/
self.send('SMSM', $game_map.map_id)
return true
when /\A\/editshop (\S+)\Z/
self.send('TSES', $1)
$game_temp.player_shop_sell_selected = $1.to_i
return true
when /\A\/buy (\S+)\Z/
self.send('SSD', $1, $game_map.map_id)
$game_temp.player_shop_buy_selected = $1.to_i
return true
when /\A\/makeshop (\S{1}.*)/
if $game_party.gold >= PlayerShopConfig::SHOP_COST
$game_party.lose_gold(PlayerShopConfig::SHOP_COST)
self.send('CNPS', @username, @user_id, $game_map.map_id, $1)
else
self.add_error(RMXOS::Data::NotEnoughMoney)
end
return true
end
return check_normal_commands_player_shops_alias(message)
end
end
end
#==============================================================================
# ** Scene_Shop
#------------------------------------------------------------------------------
# This class performs shop screen processing.
#==============================================================================
class Scene_PlayerShopSell
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
# Make help window
@help_window = Window_Help.new
# Make gold window
@gold_window = Window_Gold.new
@gold_window.x = 480
@gold_window.y = 64
# Make dummy window
@dummy_window = Window_Base.new(0, 128, 640, 352)
@dummy_window2 = Window_Base.new(0, 128, 368, 352)
@dummy_window2.visible = false
@shop_name_window = Window_PlayerShopName.new
# Make sell window
@sell_window = Window_ShopSell.new
@sell_window.active = true
@sell_window.visible = true
@sell_window.help_window = @help_window
# Make quantity input window
@number_window = Window_PlayerShopSellNumber.new
@number_window.active = false
@number_window.visible = false
@input_number_window = Window_PlayerShopInputNumber.new(6)
@input_number_window.number = 0
#@input_number_window.x = 128
#@input_number_window.y = 224
@input_number_window.visible = false
@input_number_window.active = false
# Make status window
@status_window = Window_ShopStatus.new
@status_window.visible = false
# Execute transition
Graphics.transition
# Main loop
loop do
# Update game screen
Graphics.update
# Update input information
Input.update
# Frame update
update
# Abort loop if screen is changed
if $scene != self
break
end
end
# Prepare for transition
Graphics.freeze
# Dispose of windows
@help_window.dispose
@gold_window.dispose
@dummy_window.dispose
@dummy_window2.dispose
@sell_window.dispose
@number_window.dispose
@status_window.dispose
@shop_name_window.dispose
@input_number_window.dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Update windows
@help_window.update
@gold_window.update
@dummy_window.update
@sell_window.update
@number_window.update
@status_window.update
@shop_name_window.update
$network.listen
if @input_number_window.active
@input_number_window.update
update_price_input
return
end
# If sell window is active: call update_sell
if @sell_window.active
update_sell
return
end
# If quantity input window is active: call update_number
if @number_window.active
update_number
return
end
end
#--------------------------------------------------------------------------
# * Frame Update (when price window is active)
#--------------------------------------------------------------------------
def update_price_input
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
@input_number_window.active = false
@input_number_window.visible = false
@number_window.active = true
@number_window.visible = true
#@dummy_window.visible = true
@dummy_window2.visible = false
return
end
if Input.trigger?(Input::C)
if @input_number_window.number == 0
$game_system.se_play($data_system.buzzer_se)
return
end
$game_system.se_play($data_system.shop_se)
@dummy_window.visible = true
$network.sell_item(@input_number_window.number)
@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
@input_number_window.visible = false
@input_number_window.active = false
@dummy_window2.visible = false
return
end
end
#--------------------------------------------------------------------------
# * Frame Update (when sell window is active)
#--------------------------------------------------------------------------
def update_sell
# If B button was pressed
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
# Change windows to initial mode
$scene = Scene_Map.new
$network.send('SIU', $game_temp.player_shop_sell_selected, 0)
return
end
# If C button was pressed
if Input.trigger?(Input::C)
# Get item
@item = @sell_window.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 @item.price == 0
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
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)
@number_window.active = true
@number_window.visible = true
@status_window.visible = true
@dummy_window.visible = false
end
end
#--------------------------------------------------------------------------
# * Frame Update (when quantity input window is active)
#--------------------------------------------------------------------------
def update_number
# If B button was pressed
if 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
@sell_window.active = true
@sell_window.visible = true
@status_window.visible = false
@dummy_window.visible = true
return
end
# If C button was pressed
if Input.trigger?(Input::C)
# Play shop SE
$game_system.se_play($data_system.decision_se)
$game_temp.player_shop_sell_item = @item
$game_temp.player_shop_sell_amount = @number_window.number
@number_window.active = false
@number_window.visible = false
@input_number_window.number = 0
@input_number_window.active = true
@input_number_window.visible = true
@input_number_window.set_item(@item)
@input_number_window.refresh
@dummy_window.visible = false
@dummy_window2.visible = true
return
end
return
end
end
#==============================================================================
# ** Window_PlayerShopName
#------------------------------------------------------------------------------
# Displays owner and shop name in shop screen
#==============================================================================
class Window_PlayerShopName < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 64, 480, 64)
self.contents = Bitmap.new(width - 32, height - 32)
update
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def update
self.contents.clear
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 480, 32, $game_temp.player_shop_owner + "'s " + $game_temp.player_shop_name)
end
end
#==============================================================================
# ** Window_PlayerShopSellNumber
#------------------------------------------------------------------------------
# Modified version that doesn't show how much it will sell for
#==============================================================================
class Window_PlayerShopSellNumber < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 128, 368, 352)
self.contents = Bitmap.new(width - 32, height - 32)
@item = nil
@max = 1
@number = 1
end
#--------------------------------------------------------------------------
# * Set Items, Max Quantity, and Price
#--------------------------------------------------------------------------
def set(item, max)
@item = item
@max = max
@number = 1
refresh
end
#--------------------------------------------------------------------------
# * Set Inputted Quantity
#--------------------------------------------------------------------------
def number
return @number
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
draw_item_name(@item, 4, 96)
self.contents.font.color = normal_color
self.contents.draw_text(272, 96, 32, 32, "×")
self.contents.draw_text(308, 96, 24, 32, @number.to_s, 2)
self.cursor_rect.set(304, 96, 32, 32)
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
if self.active
# Cursor right (+1)
if Input.repeat?(Input::RIGHT) and @number < @max
$game_system.se_play($data_system.cursor_se)
@number += 1
refresh
end
# Cursor left (-1)
if Input.repeat?(Input::LEFT) and @number > 1
$game_system.se_play($data_system.cursor_se)
@number -= 1
refresh
end
# Cursdr up (+10)
if Input.repeat?(Input::UP) and @number < @max
$game_system.se_play($data_system.cursor_se)
@number = [@number + 10, @max].min
refresh
end
# Cursor down (-10)
if Input.repeat?(Input::DOWN) and @number > 1
$game_system.se_play($data_system.cursor_se)
@number = [@number - 10, 1].max
refresh
end
end
end
end
#==============================================================================
# ** Window_PlayerShopInputNumber
#------------------------------------------------------------------------------
# This window is for inputting numbers, and is used within the
# message window.
#==============================================================================
class Window_PlayerShopInputNumber < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
# digits_max : digit count
#--------------------------------------------------------------------------
def initialize(digits_max)
@digits_max = digits_max
@number = 0
@item = nil
# Calculate cursor width from number width (0-9 equal width and postulate)
dummy_bitmap = Bitmap.new(32, 32)
@cursor_width = dummy_bitmap.text_size("0").width + 8
dummy_bitmap.dispose
super(0, 128, 368, 352)
self.contents = Bitmap.new(width - 32, height - 32)
self.z += 9999
self.opacity = 0
@index = 0
refresh
update_cursor_rect
end
#--------------------------------------------------------------------------
# * Get Number
#--------------------------------------------------------------------------
def number
return @number
end
#--------------------------------------------------------------------------
# * Set Number
# number : new number
#--------------------------------------------------------------------------
def number=(number)
@number = [[number, 0].max, 10 ** @digits_max - 1].min
refresh
end
#--------------------------------------------------------------------------
# * Cursor Rectangle Update
#--------------------------------------------------------------------------
def update_cursor_rect
self.cursor_rect.set(128 + @index * @cursor_width, 96, @cursor_width, 32)
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# If up or down directional button was pressed
if Input.repeat?(Input::UP) or Input.repeat?(Input::DOWN)
$game_system.se_play($data_system.cursor_se)
# Get current place number and change it to 0
place = 10 ** (@digits_max - 1 - @index)
n = @number / place % 10
@number -= n * place
# If up add 1, if down substract 1
n = (n + 1) % 10 if Input.repeat?(Input::UP)
n = (n + 9) % 10 if Input.repeat?(Input::DOWN)
# Reset current place number
@number += n * place
refresh
end
# Cursor right
if Input.repeat?(Input::RIGHT)
if @digits_max >= 2
$game_system.se_play($data_system.cursor_se)
@index = (@index + 1) % @digits_max
end
end
# Cursor left
if Input.repeat?(Input::LEFT)
if @digits_max >= 2
$game_system.se_play($data_system.cursor_se)
@index = (@index + @digits_max - 1) % @digits_max
end
end
update_cursor_rect
end
def set_item(item)
@item = item
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.font.color = normal_color
draw_item_name(@item, 4, 0)
self.contents.draw_text(128, 64, 96,32, "Price: ")
s = sprintf("%0*d", @digits_max, @number)
for i in 0...@digits_max
self.contents.draw_text(128 + i * @cursor_width + 4, 96, 32, 32, s[i,1])
end
end
end
#==============================================================================
# ** Scene_PlayerShopBuy
#------------------------------------------------------------------------------
# This class performs shop screen processing.
#==============================================================================
class Scene_PlayerShopBuy
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
# Make help window
@help_window = Window_Help.new
# Make command window
# Make gold window
@gold_window = Window_Gold.new
@gold_window.x = 480
@gold_window.y = 64
# Make dummy window
@dummy_window = Window_Base.new(0, 128, 640, 352)
@dummy_window.visible = false
@shop_name_window = Window_PlayerShopName.new
# Make buy window
@buy_window = Window_PlayerShopBuy.new #shop goods here
@buy_window.active = true
@buy_window.visible = true
@buy_window.help_window = @help_window
# Make quantity input window
@number_window = Window_ShopNumber.new
@number_window.active = false
@number_window.visible = false
# Make status window
@status_window = Window_ShopStatus.new
@status_window.visible = true
# Execute transition
Graphics.transition
# Main loop
loop do
# Update game screen
Graphics.update
# Update input information
Input.update
# Frame update
update
# Abort loop if screen is changed
if $scene != self
break
end
end
# Prepare for transition
Graphics.freeze
# Dispose of windows
@help_window.dispose
@gold_window.dispose
@dummy_window.dispose
@buy_window.dispose
@number_window.dispose
@status_window.dispose
@shop_name_window.dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Update windows
@help_window.update
@gold_window.update
@dummy_window.update
@buy_window.update
@number_window.update
@status_window.update
@shop_name_window.update
$network.listen
# If buy window is active: call update_buy
if @buy_window.active
update_buy
return
end
# If quantity input window is active: call update_number
if @number_window.active
update_number
return
end
end
#--------------------------------------------------------------------------
# * Frame Update (when buy window is active)
#--------------------------------------------------------------------------
def update_buy
# Set status window item
@status_window.item = @buy_window.item
# If B button was pressed
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
$network.send('SIU', $game_temp.player_shop_buy_selected, 0)
$scene = Scene_Map.new
return
end
# If C button was pressed
if Input.trigger?(Input::C)
# Get item
@item = @buy_window.item
# If item is invalid, or price is higher than money possessed
if @item == nil or @buy_window.get_price > $game_party.gold
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# 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
# If 99 items are already in possession
if number == 99
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Calculate maximum amount possible to buy
max = @buy_window.get_price == 0 ? 99 : $game_party.gold / @buy_window.get_price
max = [max, 99 - number, @buy_window.get_number].min
# Change windows to quantity input mode
@buy_window.active = false
@buy_window.visible = false
@number_window.set(@item, max, @buy_window.get_price)
@number_window.active = true
@number_window.visible = true
end
end
#--------------------------------------------------------------------------
# * Frame Update (when quantity input window is active)
#--------------------------------------------------------------------------
def update_number
# If B button was pressed
if 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
@buy_window.active = true
@buy_window.visible = true
return
end
# If C button was pressed
if Input.trigger?(Input::C)
# Play shop SE
$game_system.se_play($data_system.shop_se)
# Set quantity input window to inactive / invisible
@number_window.active = false
@number_window.visible = false
if $game_temp.player_shop_buy_items[1] != $network.user_id
$game_party.lose_gold(@number_window.number * @buy_window.get_price)
end
$network.send('SMP',$game_temp.player_shop_buy_items[1] ,@number_window.number * @buy_window.get_price)
case @item
when RPG::Item
type = 0
$game_party.gain_item(@item.id, @number_window.number)
when RPG::Weapon
type = 1
$game_party.gain_weapon(@item.id, @number_window.number)
when RPG::Armor
type = 2
$game_party.gain_armor(@item.id, @number_window.number)
end
shop = $game_temp.player_shop_buy_selected
id = @item.id
amount = @number_window.number
price = @buy_window.get_price
$network.send('SCD',shop, id, -amount, price, type)
@buy_window.reduce_quantity(@number_window.number)
# 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
return
end
end
end
#==============================================================================
# ** Window_PlayerShopBuy
#------------------------------------------------------------------------------
# This window displays buyable goods on the shop screen.
#==============================================================================
class Window_PlayerShopBuy < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
# shop_goods : goods
#--------------------------------------------------------------------------
def initialize
super(0, 128, 368, 352)
refresh
self.index = 0
end
#--------------------------------------------------------------------------
# * Item Acquisition
#--------------------------------------------------------------------------
def item
return nil if @data == []
return @data[self.index][0]
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
goods = $game_temp.player_shop_buy_items
for item_data in goods[3].values
next if item_data[1] <= 0
case item_data[2]
when 0
item = $data_items[item_data[3]]
when 1
item = $data_weapons[item_data[3]]
when 2
item = $data_armors[item_data[3]]
end
if item != nil
@data.push([item, item_data[0], item_data[1]]) #[item, price, amount]
end
end
if self.index >= @data.size
self.index = @data.size - 1
self.index = 0 if self.index < 0
end
# If item count is not 0, make a bit map and draw all items
@item_max = @data.size
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
for i in 0...@item_max
draw_item(i)
end
end
end
def reduce_quantity(amount)
for item_data in $game_temp.player_shop_buy_items[3].values
case item_data[2]
when 0
item = $data_items[item_data[3]]
when 1
item = $data_weapons[item_data[3]]
when 2
item = $data_armors[item_data[3]]
end
if item == self.item
item_data[1] -= amount
end
end
end
def get_price
return @data[self.index][1]
end
def get_number
return @data[self.index][2]
end
#--------------------------------------------------------------------------
# * Draw Item
# index : item number
#--------------------------------------------------------------------------
def draw_item(index)
item = @data[index][0]
# Get items in possession
case item
when RPG::Item
number = $game_party.item_number(item.id)
when RPG::Weapon
number = $game_party.weapon_number(item.id)
when RPG::Armor
number = $game_party.armor_number(item.id)
end
# If price is less than money in possession, and amount in possession is
# not 99, then set to normal text color. Otherwise set to disabled color
if @data[index][1] <= $game_party.gold and number < 99
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
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)
self.contents.draw_text(x + 28, y, 212, 32, item.name + " [QTY: " + @data[index][2].to_s + "]", 0)
self.contents.draw_text(x + 240, y, 88, 32, @data[index][1].to_s, 2)
end
#--------------------------------------------------------------------------
# * Help Text Update
#--------------------------------------------------------------------------
def update_help
@help_window.set_text(self.item == nil ? "" : self.item.description)
end
end
class Game_Temp
attr_accessor :player_shop_sell_item
attr_accessor :player_shop_sell_amount
attr_accessor :player_shop_sell_selected
attr_accessor :player_shop_owner
attr_accessor :player_shop_name
attr_accessor :player_shop_buy_items
attr_accessor :player_shop_buy_selected
alias initialize_player_shops initialize
def initialize
@player_shop_sell_item = nil
@player_shop_sell_amount = 0
@player_shop_sell_selected = 0
@player_shop_owner = ""
@player_shop_name = ""
@player_shop_buy_items = {}
@player_shop_buy_selected = 0
initialize_player_shops
end
end