01-14-2019, 10:40 AM
(This post was last modified: 01-15-2019, 03:30 AM by kyonides.
Edit Reason: Updated Code! Finished Implementing Favors
)
Here I come again! Nope, I ain't singing here!
A while ago I finished a new release of KyoDiscounts XP where game developers will now feel free to include extra features like haggling! The benefits would be that it would count as a favor so the storekeeper alias appraiser might be able to offer extra goods after finishing his or her appraisal. Nope, don't worry, pals! They won't get more than a single good at a time. The difference would be that the player would be able to get a chance to get a good that wasn't available before doing him or her a favor...or series of favors. If the appraisal results in a great finding that captivates the appraiser, he or she will make you an offer and even a second and final offer if you allow that!
Happy Game Testing!?
Edit: I have finished implementing favors so now the shopkeeper alias appraiser should recall how many times you have brought and sold interesting items to him or her.
I don't know why I let wulfo convince me of adding such a weird feature, namely the haggling part... =_=
A while ago I finished a new release of KyoDiscounts XP where game developers will now feel free to include extra features like haggling! The benefits would be that it would count as a favor so the storekeeper alias appraiser might be able to offer extra goods after finishing his or her appraisal. Nope, don't worry, pals! They won't get more than a single good at a time. The difference would be that the player would be able to get a chance to get a good that wasn't available before doing him or her a favor...or series of favors. If the appraisal results in a great finding that captivates the appraiser, he or she will make you an offer and even a second and final offer if you allow that!
Happy Game Testing!?
Edit: I have finished implementing favors so now the shopkeeper alias appraiser should recall how many times you have brought and sold interesting items to him or her.
Code:
# * KyoDiscounts XP
# Scripter : Kyonides-Arkanthes
# v1.5.0 - 2019-01-14
# Whenever you obtain a discount card, such discount will be applied to all
# of your purchases if you have picked a card till it expires after a certain
# number of steps. Additional steps will be quickly added to your current card
# whenever you purchase any additional card of the same kind.
# One coupon will be spent every single time you purchase any specific item,
# you will need another one to purchase a different item later on.
# The discount card or coupon price is used to calculate the corresponding
# discount on every single purchase the player makes with it.
# Place this script below KItemRefill XP or KyoScriptPack Item XP if you
# included any of those scripts in your current game project.
# Now you can also setup exclusive store discount cards as well. Just keep in
# mind that you will need to setup the in game variable you picked so it will
# be able to store the Exclusive Store Code (an Integer) before you can add
# the shop event command. Common stores don't need any Store Code at all.
# Besides the player can also place orders to get an item that is supposed to
# be found at another store only. The player will be charged an extra fee, but
# he or she won't need to go back to another store. The player would only need
# to keep walking for a while before the goods are available at the store.
# Now the required steps for each placed order will be automatically increased
# between 0% and 50%, making it look a bit random but also kind of realistic.
# * Unknown Item or Weapon or Armor Appraisals *
# Use the Game Variable defined in the STORECODEVARID Constant to store the
# Shop ID that will include the appraisal service.
# Use the MYSTERIOUS series of Arrays to include as many IDs of unknown items
# or weapons or armors that will serve as fillers till they get replaced by
# the actual goods they represent.
# Follow the Instructions included in the APPRAISALS Hash to define all
# conditions that will affect an appraiser's task of identifying the item.
# Script Calls #
# $game_party.discount_cards_expire
# Makes all Discount Cards expire as part of the game's plot.
# $game_party.disc_card_expire(Card_ID)
# Makes an specific Discount Card expire as part of the game's plot.
# KyoShopOrders << [Percent1, Percent2, etc.]
# Defines a Commission percent for every Item in the Place Order List.
# KyoShopOrders.steps = [Steps1, Steps2, etc.]
# KyoShopOrders.steps += [Steps5, Steps6, etc.]
# Defines Steps required by every Order in the Place Order List.
# The 2nd call will be required only if you couldn't include all steps.
# KyoShop.scarcity_lvl = 0 or higher
# Define all prices and maximum number of units per shop item.
# 0 means no scarcity, 1 or higher reflects how severe it is.
# You also have to configure the @scarce_limits hash in order to predefine
# :price and :max per scarcity level. The maximum scarcity level depends on
# how many values you entered in both :price and :max arrays.
# In few words, you define the maximum scarcity level ever possible!
module KyoShop
# Maximum number of units for each shop item
NUMBERMAX = 99
# Button that will open the Discount window while on the shop menu
DISCOUNTBUTTON = Input::A
# Add Discount Card Object IDs
DISCOUNT_IDS = [33, 34]
# Add Discount Coupon Object IDs
COUPON_IDS = [36, 37]
# Maximum Steps before Discount Card expires : ID => Steps
STEPS = { 33 => 500, 34 => 300, 35 => 150 }
# Exclusive Stores In Game Variable ID
STORECODEVARID = 1
# Exclusive Stores List : Object ID => Exclusive Store Code
EXCLUSIVESTORES = { 35 => 102 }
# Switch ID : deactivates Store to add Goods found elsewhere
GOODSSWITCHID = 1
# Store IDs for stores where you have invested some gold
INVESTSTOREIDS = [101]
# Maximum Number of Shares & Share Price
SHARESMAXMIN = [10000, 100]
INVESTMENTS = {} # Store Investments - Do Not Edit This Line
INVESTMENTS.default = {} # Do Not Edit This Line
# Available Improvements #
# :discount : [:discount, 25]
# :goods : [:goods, 'i10', 'w4', 'a6']
# :orders : [:orders, 'i11', 'w5', 'a7']
# [Store ID] = { Shares => Prize, Shares => Another Prize, etc. }
INVESTMENTS[101] = { 50 => [:goods,'i10','w5','a6'], 100 => [:discount,10] }
APPRAISALS = {} # Do Not Edit This Line!
# [Store ID] = { appraisal cost => $, estimate cost => $, success rate => %,
# times you can help the a. => 0, bad result => "i1", goods => [item4, etc.] }
APPRAISALS[101] = { :cost => 150, :test_cost => 75, :rate => 10,
:default => 'i1', :help_limit => 5, :haggle => true,
:target => { 'i9' => 1, 'i10' => 2 },
:goods => ['i2','i3','i9','i10'], :extras => ['i11'] }
# Add Item IDs for unknown shop goods that need to be appraised by experts
MYSTERIOUSITEMS = []
# Add Weapon IDs for unknown shop goods that need to be appraised by experts
MYSTERIOUSWEAPONS = []
# Add Armor IDs for unknown shop goods that need to be appraised by experts
MYSTERIOUSARMORS = []
@scarce_limits = {
:price => [0, 25, 50, 100, 250, 350, 500, 650, 800],
:max => [NUMBERMAX, NUMBERMAX - 10, NUMBERMAX - 25, NUMBERMAX - 35,
NUMBERMAX - 50, NUMBERMAX - 65, NUMBERMAX - 80, NUMBERMAX - 90, 1]
#:item => [1, 2, 3, 4, 5, 6],
#:weapon => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
#:armor => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
}
@scarce_lvl = 0 # Initial Level
def self.current_item_max() @scarce_limits[:max][@scarce_lvl] end
def self.current_price_max() @scarce_limits[:price][@scarce_lvl] end
def self.scarcity_limits() @scarce_limits end
def self.scarcity_lvl() @scarce_lvl end
def self.scarcity_lvl=(lvl) @scarce_lvl = lvl end
end
module KyoShopLabels
# Basic Shop Command Labels
BASIC = ["Buy", "Sell", "Exit"]
MOREOPTIONS = "Options"
# Buy Stuff & Place Order & Pick Up Items Label
BUYPLACEPICKUP = ['Buy Items', 'Place Order', 'Pick Up Items',
'Appraise', 'Invest']
# Subtotal, Commission Percent and Total Amount
PRICELABELS = ['Subtotal', 'Commission %', 'Total']
# Place an Order Label
PLACEORDER = 'Do you wish to place an order?'
# Pick Up Order Label
PICKUPORDER = 'Do you want to pick up an order?'
# No Order Found Label
NOORDERFOUND = 'There is nothing left, boss!'
# Available Discounts Label
SOMEDISCOUNTS = 'Press A to get a discount'
# No Discount Available Label
NODISCOUNTS = 'No Discount Available'
# Select a Discount Card or Coupon Label
SELECTDISCOUNT = 'Choose a Card or Coupon'
# Apply Discount Label
APPLYDISCOUNT = "Discount Applied %s%"
# Warning about Extra Fees for Placing Orders
FEESAPPLY = 'Extra Fees Apply'
# Discount Card's Steps Left Label
STEPSLEFT = " %s steps left."
# Investment Label...
INVESTMENT = 'Want to invest in this store?'
# Share Number Label
SHARES = 'Share Number'
# Adquired or Purchased Shares Label
TOTALSHARES = 'Total Shares'
# Pick Item to be Appraised Label
APPRAISALMENULABEL = "Appraisal Menu"
# Appraisal Window Labels
APPRAISALLABELS = ["Quick Test Cost", "Normal Cost"]
# Appraisal Options Labels
APPRAISALOPTIONS = ["Quick Test", "Detailed Test", "Cancel"]
# Purchase Offer and Haggle Labels
APPRAISALHAGGLEOPTIONS = ["Accept", "Haggle", "Decline"]
# Appraisal End Result Labels
APPRAISALRESULTLABELS = [
"The item at hand is nothing else but... %s",
"I think it might be worth some... %s",
"I've been searching for some %s!",
"Now I want to make a deal.",
"What if I make a better offer?",
"Would you accept some %s?"
]
end
# DO NOT EDIT ANYTHING ELSE #
module KyoShopOrders
@commissions = []
@steps = []
class << self
attr_accessor :store_event_id, :goods_id
attr_reader :steps, :commissions
def steps=(val) @steps = val.map {|n| n + rand((n / 2) + 2) } end
def <<(val)
@commissions += val
@commissions = @commissions.flatten
end
end
end
module WindowModule
def appear
self.active = true
self.visible = true
end
def disappear
self.active = false
self.visible = false
end
end
class Game_System
attr_accessor :shop_goods
attr_reader :placed_orders, :shop_shares, :shop_favors
alias kyon_discounts_gm_sys_init initialize
def initialize
@shop_goods = []
@placed_orders = {}
@shop_shares = {}
@shop_favors = {}
@placed_orders.default = []
@shop_shares.default = 0
@shop_favors.default = 0
kyon_discounts_gm_sys_init
end
def disc_store?(disc_id) !KyoShop::EXCLUSIVESTORES[disc_id] end
def excl_disc_store?(disc_id)
exclusive = KyoShop::EXCLUSIVESTORES[disc_id]
$game_variables[KyoShop::STORECODEVARID] == exclusive
end
def check_shares(shop_id)
results = []
shares = @shop_shares[shop_id]
investments = KyoShop::INVESTMENTS[shop_id]
limits = KyoShop::INVESTMENTS[shop_id].keys.sort
results = investments.select{|limit| shares >= limit[0] }.map {|r| r[1] }
end
end
class Game_Party
attr_reader :discounts
alias kyon_discounts_gm_party_init initialize
alias kyon_discounts_gm_party_gain_item gain_item
def initialize
@discounts = {}
kyon_discounts_gm_party_init
end
def gain_item(item_id, n)
kyon_discounts_gm_party_gain_item(item_id, n)
return if item_id == 0 or n == 0
return unless KyoShop::DISCOUNT_IDS.include?(item_id)
if @discounts[item_id]
@discounts[item_id] += KyoShop::STEPS[item_id]
@items[item_id] = 1
else
@discounts[item_id] = KyoShop::STEPS[item_id]
end
end
def check_discounts
unless @discounts.empty?
for did in KyoShop::DISCOUNT_IDS
next unless @discounts[did] and @discounts[did] > 0
return true if $game_system.disc_store?(did)
return true if $game_system.excl_disc_store?(did)
end
end
for cid in KyoShop::COUPON_IDS
next unless item_number(cid) > 0
return true if $game_system.disc_store?(cid)
return true if $game_system.excl_disc_store?(cid)
end
return false
end
def decrease_discounts
KyoShop::DISCOUNT_IDS.each {|n| next unless @discounts[n]
@discounts[n] -= 1 if @discounts[n] > 0 }
end
def discount_cards_expire
KyoShop::DISCOUNT_IDS.each {|n| @discounts[n] = 0 if @discounts[n] }
end
def disc_card_expire(dc_id) @discounts[dc_id] = 0 end
end
class Game_Player
alias kyon_discounts_coupons_gm_player_increase_steps increase_steps
def increase_steps
kyon_discounts_coupons_gm_player_increase_steps
$game_party.decrease_discounts
end
end
class Window_Selectable
include WindowModule
end
class Window_Help
def set_text(item_id, text=nil, align=0)
if item_id.is_a?(String)
if KyoShop::DISCOUNT_IDS.include?(KyoShopOrders.goods_id)
steps = $game_party.discounts[KyoShopOrders.goods_id].to_s
text = item_id + sprintf(KyoShopLabels::STEPSLEFT, steps)
KyoShopOrders.goods_id = item_id = nil
end
end
if text.is_a?(String)
text = text.gsub(/\\[Uu]/){$game_system.refill_items[item_id].sips.to_s}
elsif text.is_a?(Integer)
align = text
text = item_id
else
text = item_id
end
if text != @text or align != @align
self.contents.clear
self.contents.font.color = normal_color
self.contents.draw_text(4, 0, self.width - 40, 32, text, align)
@text = text
@align = align
@actor = nil
end
self.visible = true
end
end
class Window_Item
alias kyon_discounts_win_item_up_help update_help
def update_help
KyoShopOrders.goods_id = self.item.id
kyon_discounts_win_item_up_help
end
end
class AppraiseItemWindow < Window_Selectable
def initialize
super(0, 64, 480, 320)
@column_max = 1
refresh
self.index = 0
end
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
for n in KyoShop::MYSTERIOUSITEMS
next if $game_party.item_number(n) == 0
@data << $data_items[n]
end
for i in KyoShop::MYSTERIOUSWEAPONS
next if $game_party.weapon_number(i) == 0
@data << $data_weapons[i]
end
for i in KyoShop::MYSTERIOUSARMORS
next if $game_party.armor_number(i) == 0
@data << $data_armors[i]
end
@item_max = @data.size
return if @item_max == 0
self.contents = Bitmap.new(width - 32, row_max * 32)
@item_max.times{|i| draw_item(i) }
end
def draw_item(index)
item = @data[index]
number = case item
when RPG::Item then $game_party.item_number(item.id)
when RPG::Weapon then $game_party.weapon_number(item.id)
when RPG::Armor then $game_party.armor_number(item.id)
end
c = self.contents
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
c.fill_rect(rect, Color.new(0, 0, 0, 0))
bit = RPG::Cache.icon(item.icon_name)
c.blt(x, y + 4, bit, Rect.new(0, 0, 24, 24), 255)
c.draw_text(x + 28, y, 212, 32, item.name, 0)
c.draw_text(x + 240, y, 16, 32, ":", 1)
c.draw_text(x + 256, y, 24, 32, number.to_s, 2)
end
def item() @data[@index] end
def empty?() @data.empty? end
end
class AppraiseInfoWindow < Window_Base
def initialize(store_id)
super(480, 128, 160, 256)
@data = KyoShop::APPRAISALS[store_id]
@labels = KyoShopLabels::APPRAISALLABELS.dup
@currency = $data_system.words.gold
self.contents = Bitmap.new(width - 32, height - 32)
refresh
end
def refresh
aw = width - 32
contents.clear
contents.font.color = system_color
contents.draw_text(0, 0, aw, 24, @labels[0])
contents.draw_text(0, 48, aw, 24, @labels[1])
contents.draw_text(0, 24, aw, 24, @currency, 2)
contents.draw_text(0, 72, aw, 24, @currency, 2)
contents.font.color = normal_color
contents.draw_text(0, 24, width - 48, 24, @data[:test_cost].to_s, 2)
contents.draw_text(0, 72, width - 48, 24, @data[:cost].to_s, 2)
end
end
class AppraiseResultWindow < Window_Base
def initialize
super(0, 384, 640, 96)
@labels = KyoShopLabels::APPRAISALRESULTLABELS.dup
@currency = $data_system.words.gold
self.contents = Bitmap.new(width - 32, height - 32)
end
def refresh(item)
contents.clear
result = sprintf(@labels[0], item.name)
cost = sprintf(@labels[1], item.price) + " " + @currency
contents.draw_text(0, 0, width - 32, 24, result)
contents.draw_text(0, 24, width - 32, 24, cost)
end
def ask_favor(item)
contents.clear
result = sprintf(@labels[2], item.name)
contents.draw_text(0, 0, width - 32, 24, result)
contents.draw_text(0, 24, width - 32, 24, @labels[3])
end
def make_offer(overprice)
contents.clear
result = sprintf(@labels[5], overprice) + " " + @currency
contents.draw_text(0, 0, width - 32, 24, @labels[4])
contents.draw_text(0, 24, width - 32, 24, result)
end
end
class Window_ShopCommand
def initialize
super(0, 64, 480, 64)
self.contents = Bitmap.new(width - 32, height - 32)
@item_max = 3
@column_max = 3
@commands = KyoShopLabels::BASIC.dup
if KyoShop::APPRAISALS[$game_variables[KyoShop::STORECODEVARID]]
@commands[0] = KyoShopLabels::MOREOPTIONS.dup
end
refresh
self.index = 0
end
end
class Window_ShopBuy
attr_accessor :discount
def initialize(shop_goods)
super(0, 128, 368, 288)
@shop_goods = shop_goods
@discount = 0
refresh
self.index = 0
end
def deliver(goods)
@shop_goods = goods
if goods.size - 1 < @index
@index = goods.size > 0 ? (@index + goods.size - 1) % goods.size : 0
update_cursor_rect
end
refresh
self.index = 0
end
def draw_item(index)
item = @data[index]
number = case item
when RPG::Item then $game_party.item_number(item.id)
when RPG::Weapon then $game_party.weapon_number(item.id)
when RPG::Armor then $game_party.armor_number(item.id)
end
enough = (item.price <= $game_party.gold and number < 99)
self.contents.font.color = enough ? normal_color : disabled_color
y = index * 32
rect = Rect.new(4, y, self.width - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = enough ? 255 : 128
self.contents.blt(4, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(32, y, 212, 32, item.name, 0)
price = item.price - item.price * @discount / 100
self.contents.draw_text(244, y, 88, 32, price.to_s, 2)
end
end
class Window_ShopPickUp < Window_ShopBuy
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
for good in @shop_goods
new_item = case good[0]
when 0 then $data_items[good[1]]
when 1 then $data_weapons[good[1]]
when 2 then $data_armors[good[1]]
end
@data << new_item if new_item
end
@item_max = @data.size
return if @item_max == 0
self.contents = Bitmap.new(width - 32, row_max * 32)
(0...@item_max).each {|i| draw_item(i) }
end
def draw_item(index)
item = @data[index]
qty, steps = @shop_goods[index][2..3]
number = case item
when RPG::Item then $game_party.item_number(item.id)
when RPG::Weapon then $game_party.weapon_number(item.id)
when RPG::Armor then $game_party.armor_number(item.id)
end
enough = (number + qty < 100 and steps <= $game_party.steps)
self.contents.font.color = enough ? normal_color : disabled_color
y = index * 32
rect = Rect.new(4, y, self.width - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = enough ? 255 : 128
self.contents.blt(4, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(32, y, 212, 32, item.name, 0)
self.contents.draw_text(244, y, 88, 32, qty.to_s, 2)
end
undef discount, discount=
end
class Window_ShopNumber
include WindowModule
def initialize
super(0, 128, 368, 288)
self.contents = Bitmap.new(width - 32, height - 32)
@item = nil
@max = 1
@price = 0
@number = 1
@multiplier = 1
end
def reset_multiplier
@multiplier = 1
@number = 1
refresh
end
def set(item, max, price, percent=nil, multiplier=1)
@item = item
@max = max
@price = price
@number = 1
@multiplier = multiplier
@percent = percent
refresh
end
def update
super
return unless self.active
if Input.repeat?(Input::RIGHT) and @number < @max
$game_system.se_play($data_system.cursor_se)
@number += @multiplier
refresh
end
if Input.repeat?(Input::LEFT) and @number > @multiplier
$game_system.se_play($data_system.cursor_se)
@number -= @multiplier
refresh
end
if Input.repeat?(Input::UP) and @number < @max
$game_system.se_play($data_system.cursor_se)
@number = [@number + 10 * @multiplier, @max].min
refresh
end
if Input.repeat?(Input::DOWN) and @number > @multiplier
$game_system.se_play($data_system.cursor_se)
@number = [@number - 10 * @multiplier, 1].max
refresh
end
end
def refresh
self.contents.clear
draw_item_name(@item, 4, 96)
self.contents.font.color = normal_color
if @multiplier == 1
cx1, cx2, cx3, cw1, cw2 = [272, 308, 304, 24, 32]
else
cx1, cx2, cx3, cw1, cw2 = [260, 264, 272, 68, 64]
end
self.contents.draw_text(cx1, 96, 32, 32, "")
self.contents.draw_text(cx2, 96, cw1, 32, @number.to_s, 2)
self.cursor_rect.set(cx3, 96, cw2, 32)
gold = $data_system.words.gold
cx = contents.text_size(gold).width
subtotal_price = @item.price * @number
total_price = @price * @number
labels = KyoShopLabels::PRICELABELS
if total_price > subtotal_price and @multiplier < 2
self.contents.font.color = system_color
self.contents.draw_text(120, 128, 100, 32, labels[0], 2)
self.contents.draw_text(332-cx, 128, cx, 32, gold, 2)
self.contents.draw_text(80, 160, 140, 32, labels[1], 2)
self.contents.draw_text(328-cx, 160, cx + 4, 32, '%', 2)
self.contents.font.color = normal_color
self.contents.draw_text(4, 128, 328-cx-2, 32, subtotal_price.to_s, 2)
self.contents.draw_text(4, 160, 328-cx-2, 32, @percent.to_s, 2)
end
self.contents.draw_text(4, 192, 328-cx-2, 32, total_price.to_s, 2)
self.contents.font.color = system_color
self.contents.draw_text(120, 192, 100, 32, labels[2], 2)
self.contents.draw_text(332-cx, 192, cx, 32, gold, 2)
end
end
class Window_ShopBuyOptions < Window_Selectable
def initialize
commands = KyoShopLabels::BUYPLACEPICKUP.dup
varid = $game_variables[KyoShop::STORECODEVARID]
commands.pop unless KyoShop::INVESTSTOREIDS.include?(varid)
super(214, 148, 212, commands.size * 32 + 32)
@commands = commands
@item_max = @commands.size
self.contents = Bitmap.new(width - 32, @item_max * 32)
refresh
self.index = 0
end
def refresh
self.contents.clear
@item_max.times {|i| @commands[i]
contents.draw_text(4, i * 32, 172, 32, @commands[i]) }
end
end
class Window_ShopDiscountAlert < Window_Base
def initialize
super(0, 416, 368, 64)
self.contents = Bitmap.new(width - 32, height - 32)
end
def set_text(text)
self.contents.clear
self.contents.draw_text(0, 0, width - 32, height - 32, text)
end
end
class Window_ShopDiscountCoupon < Window_Selectable
def initialize
super(0, 128, 368, 288)
self.index = 0
refresh
end
def item() @data[@index] end
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
dc_ids = $game_party.discounts.keys.sort
dc_ids.each {|i| next if $game_party.discounts[i] == 0
next if !$game_system.disc_store?(i) and !$game_system.excl_disc_store?(i)
@data << $data_items[i] }
KyoShop::COUPON_IDS.each {|i| next unless $game_party.item_number(i) > 0
@data << $data_items[i] }
@item_max = @data.size
return if @item_max == 0
self.index -= 1 if @index > @item_max - 1
self.contents = Bitmap.new(width - 32, row_max * 32)
(0...@item_max).each {|i| draw_item(i) }
end
def draw_item(index)
item = @data[index]
number = $game_party.item_number(item.id)
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)
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), 255)
self.contents.draw_text(x + 28, y, 212, 32, item.name)
self.contents.draw_text(x + 28, y, 244, 32, ': ' + number.to_s, 2)
end
def update_help
KyoShopOrders.goods_id = self.item.id
@help_window.set_text(self.item.description)
end
end
class Window_ShopStatus
alias kyon_discounts_win_shop_status_refresh refresh
def refresh
if @investment
refresh_investment
return
end
kyon_discounts_win_shop_status_refresh
end
def investment=(bool)
@investment = bool
refresh
end
def refresh_investment
shares = $game_system.shop_shares[$game_variables[KyoShop::STORECODEVARID]]
contents.font.color = system_color
contents.draw_text(0, 0, 240, 32, KyoShopLabels::TOTALSHARES)
contents.font.color = normal_color
contents.draw_text(0, 0, 240, 32, shares.to_s, 2)
end
end
class Interpreter
alias kyon_discounts_inter_comm_302 command_302
def command_302
if $game_switches[KyoShop::GOODSSWITCHID]
KyoShopOrders.store_event_id = @event_id
$game_switches[KyoShop::GOODSSWITCHID] = false
$game_system.shop_goods = [@parameters]
loop do
@index += 1
if @list[@index].code == 605
$game_system.shop_goods << @list[@index].parameters
else
return false
end
end
end
kyon_discounts_inter_comm_302
end
end
class Scene_Shop
alias kyon_discounts_scn_shop_up update
def main
start
Graphics.transition
while @keep_loop
Graphics.update
Input.update
update
end
Graphics.freeze
terminate
end
def start
@keep_loop = true
@stage = :main
@shop_id = $game_variables[KyoShop::STORECODEVARID]
@goods = $game_temp.shop_goods.dup
@orders = $game_system.shop_goods.dup
update_goods_orders_after_investment
make_basic_windows
@discount_window = Window_ShopDiscountCoupon.new
@discount_window.disappear
@discount_window.help_window = @help_window
unless $game_system.shop_goods.empty?
@order_window = Window_ShopBuy.new($game_system.shop_goods)
@order_window.disappear
@order_window.help_window = @help_window
@option_window = Window_ShopBuyOptions.new
@option_window.z += 200
@option_window.disappear
end
if (@need_appraisal = KyoShop::APPRAISALS.keys.include?(@shop_id))
@appraise_item_window = AppraiseItemWindow.new
@appraise_item_window.visible = false
@appraise_info_window = AppraiseInfoWindow.new(@shop_id)
@appraise_info_window.visible = false
options = KyoShopLabels::APPRAISALOPTIONS.dup
@appraise_options = Window_Command.new(160, options)
@appraise_options.disappear
@appraise_options.x = 240
@appraise_options.y = 200
@result_info_window = AppraiseResultWindow.new
options = KyoShopLabels::APPRAISALHAGGLEOPTIONS.dup
@favor_options = Window_Command.new(160, options)
@favor_options.disappear
@favor_options.x = 240
@favor_options.y = 200
else
@option_window.disable_item(3)
end
@purchase_window = Window_ShopBuy.new($game_temp.shop_goods)
@purchase_window.disappear
@purchase_window.help_window = @help_window
@pack_id = [$game_map.map_id, KyoShopOrders.store_event_id]
goods = $game_system.placed_orders[@pack_id]
goods ||= []
@pickup_window = Window_ShopPickUp.new(goods)
@pickup_window.disappear
@pickup_window.help_window = @help_window
@sell_window = Window_ShopSell.new
@sell_window.disappear
@sell_window.help_window = @help_window
@number_window = Window_ShopNumber.new
@number_window.disappear
@status_window = Window_ShopStatus.new
@status_window.visible = false
end
def update_goods_orders_after_investment
gds = []
orders = []
stuff = $game_system.check_shares(@shop_id)
return if stuff.empty?
stuff.each {|b| gds += strings_goods_conversion(b[1..-1]) if b[0] == :goods
orders += string_good_conversion(b[1..-1]) if b[0] == :orders }
$game_system.shop_goods = (@orders + orders).sort.uniq
$game_temp.shop_goods = (@goods + gds).sort.uniq
end
def strings_goods_conversion(strings)
data = []
strings.each {|string| data << retrieve_item(string) }
data
end
def retrieve_item(string)
case string[0,1]
when 'i' then [0, string[1..-1].to_i]
when 'w' then [1, string[1..-1].to_i]
when 'a' then [2, string[1..-1].to_i]
end
end
def make_basic_windows
@help_window = Window_Help.new
@command_window = Window_ShopCommand.new
@gold_window = Window_Gold.new
@gold_window.x = 480
@gold_window.y = 64
@dummy_window = Window_Base.new(0, 128, 640, 352)
@question_window = Window_ShopDiscountAlert.new
@question_window.visible = false
end
def terminate
@help_window.dispose
@command_window.dispose
@gold_window.dispose
@dummy_window.dispose
@purchase_window.dispose
@pickup_window.dispose
@sell_window.dispose
@number_window.dispose
@status_window.dispose
@question_window.dispose
@discount_window.dispose
$game_variables[KyoShop::STORECODEVARID] = 0
if @need_appraisal
@appraise_item_window.dispose
@appraise_info_window.dispose
@appraise_options.dispose
@result_info_window.dispose
@favor_options.dispose
end
return if $game_system.shop_goods.empty?
@order_window.dispose
@option_window.dispose
$game_system.shop_goods.clear
KyoShopOrders.commissions.clear
KyoShopOrders.steps.clear
KyoShopOrders.store_event_id = nil
@stage = nil
end
def update_discount_message
cd = $game_party.check_discounts
text = cd ? KyoShopLabels::SOMEDISCOUNTS : KyoShopLabels::NODISCOUNTS
@question_window.set_text(text)
end
def update
@help_window.update
@gold_window.update
@dummy_window.update
@sell_window.update
@status_window.update
case @stage
when :main then update_command
when :option then update_option
when :purchase then update_purchase
when :place then update_place_order
when :pickup then update_pickup_order
when :discount then update_discount
when :appraise then update_appraisal
when :appraise_option then update_appraisal_option
when :appraise_favor then update_appraisal_favor
when :sell then update_sell
when :number then update_number
end
end
def update_command
@command_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return @keep_loop = nil
elsif Input.trigger?(Input::C)
case @command_window.index
when 0 # buy
$game_system.se_play($data_system.decision_se)
@command_window.active = false
if $game_system.shop_goods.empty?
@discount = 0
@dummy_window.visible = false
@question_window.visible = true
@status_window.visible = true
@purchase_window.appear
@purchase_window.refresh
update_discount_message
return @stage = :purchase
else
@option_window.appear
return @stage = :option
end
when 1 # sell
$game_system.se_play($data_system.decision_se)
@command_window.active = false
@dummy_window.visible = false
@sell_window.appear
@sell_window.refresh
return
when 2 # quit
$game_system.se_play($data_system.decision_se)
$scene = Scene_Map.new
@keep_loop = nil
end
end
end
def update_option
@option_window.update
@order_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@option_window.disappear
@status_window.visible = false
@command_window.active = true
@dummy_window.visible = true
return @stage = :main
elsif Input.trigger?(Input::C)
shares = $game_system.shop_shares[@shop_id]
inv_max, inv_price = KyoShop::SHARESMAXMIN
pos = @option_window.index
if pos == 3 and !@need_appraisal
return $game_system.se_play($data_system.buzzer_se)
end
if pos == 4 and inv_max == shares
return $game_system.se_play($data_system.buzzer_se)
end
$game_system.se_play($data_system.decision_se)
@dummy_window.visible = false
@option_window.disappear
@question_window.visible = true
@status_window.visible = true
case pos
when 0 # buy
@discount = 0
@purchase_window.discount = 0
disc = $game_system.check_shares(@shop_id)
disc.each {|b| @purchase_window.discount += b[1] if b[0] == :discount }
@status_window.item = @purchase_window.item
@purchase_window.refresh
@purchase_window.appear
update_discount_message
return @stage = :purchase
when 1 # place order
@status_window.item = @order_window.item
@order_window.appear
@order_window.refresh
@question_window.set_text(KyoShopLabels::PLACEORDER)
return @stage = :place
when 2 # pick up stuff
@status_window.item = @pickup_window.item
@pickup_window.appear
@pickup_window.refresh
@question_window.set_text(KyoShopLabels::PICKUPORDER)
return @stage = :pickup
when 3 # appraisal
@appraise_item_window.appear
@appraise_info_window.visible = true
@result_info_window.visible = true
@dummy_window.visible = false
@command_window.visible = false
@number_window.visible = false
@status_window.visible = false
@help_window.set_text(KyoShopLabels::APPRAISALMENULABEL)
return @stage = :appraise
when 4 # investments
@status_window.investment = @investment = true
inv_max = [inv_max - shares, $game_party.gold / inv_price].min
fake_item = RPG::Item.new
fake_item.name = KyoShopLabels::SHARES
@price = inv_price
@number_window.set(fake_item, inv_max, inv_price, nil, 10)
@number_window.appear
@question_window.set_text(KyoShopLabels::INVESTMENT)
@stage = :number
end
end
end
def update_purchase
@purchase_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
if $game_system.shop_goods.empty?
@command_window.active = true
@stage = :main
else
@option_window.appear
@stage = :option
end
@discount = 0
@purchase_window.discount = 0
@dummy_window.visible = true
@purchase_window.disappear
@question_window.visible = false
@status_window.visible = false
@status_window.item = nil
@help_window.set_text("")
return
end
if Input.trigger?(Input::UP) or Input.trigger?(Input::DOWN)
@status_window.item = @purchase_window.item
return
end
if Input.trigger?(KyoShop::DISCOUNTBUTTON)
unless $game_party.check_discounts
return $game_system.se_play($data_system.buzzer_se)
end
$game_system.se_play($data_system.decision_se)
@purchase_window.disappear
@discount_window.refresh
@discount_window.appear
@question_window.set_text(KyoShopLabels::SELECTDISCOUNT)
return @stage = :discount
elsif Input.trigger?(Input::C)
discount = @purchase_window.discount
percent = KyoShop.current_price_max
@item = @purchase_window.item
@price = @item.price + @item.price * percent / 100
@price -= @item.price * discount / 100 if discount > 0
if @item == nil or @price > $game_party.gold
return $game_system.se_play($data_system.buzzer_se)
end
shop_max = KyoShop.current_item_max
if (number = check_number) == shop_max
return $game_system.se_play($data_system.buzzer_se)
end
$game_system.se_play($data_system.decision_se)
max = @price == 0 ? shop_max : $game_party.gold / @price
max = [max, shop_max - number].min
@purchase_window.disappear
@number_window.set(@item, max, @price)
@number_window.appear
@last_stage = @stage
@stage = :number
end
end
def update_place_order
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@option_window.appear
@dummy_window.visible = true
@order_window.disappear
@question_window.visible = false
@status_window.visible = false
@status_window.item = nil
@help_window.set_text("")
return @stage = :option
end
if Input.trigger?(Input::UP) or Input.trigger?(Input::DOWN)
@status_window.item = @order_window.item
return
end
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
@item = @order_window.item
@price = @item.price
percent = KyoShopOrders.commissions[@order_window.index]
percent += KyoShop.current_price_max
@price += percent * @item.price / 100 if percent > 0
if @item == nil or @price > $game_party.gold
return $game_system.se_play($data_system.buzzer_se)
end
number = check_number
shop_max = KyoShop.current_item_max
if number == shop_max
return $game_system.se_play($data_system.buzzer_se)
end
$game_system.se_play($data_system.decision_se)
max = @price == 0 ? shop_max : $game_party.gold / @price
max = [max, shop_max - number].min
@order_window.disappear
@place_order = true
@number_window.set(@item, max, @price, percent)
@number_window.appear
@question_window.set_text(KyoShopLabels::FEESAPPLY)
@last_stage = @stage
@stage = :number
end
end
def update_pickup_order
@pickup_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@dummy_window.visible = true
@question_window.visible = false
@status_window.visible = false
@pickup_window.disappear
@option_window.appear
return @stage = :option
end
if Input.trigger?(Input::UP) or Input.trigger?(Input::DOWN)
@status_window.item = @pickup_window.item
return
end
if Input.trigger?(Input::C)
current_item = @pickup_window.item
goods = $game_system.placed_orders[@pack_id]
unless goods
return $game_system.se_play($data_system.buzzer_se)
end
goods = goods[@pickup_window.index]
unless current_item and goods[3] <= $game_party.steps
return $game_system.se_play($data_system.buzzer_se)
end
$game_system.se_play($data_system.decision_se)
number = goods[2]
case current_item
when RPG::Item then $game_party.gain_item(current_item.id, number)
when RPG::Weapon then $game_party.gain_weapon(current_item.id, number)
when RPG::Armor then $game_party.gain_armor(current_item.id, number)
end
$game_system.placed_orders[@pack_id].delete_at(@pickup_window.index)
@pickup_window.deliver($game_system.placed_orders[@pack_id])
end
end
def update_discount
@discount_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@discount_window.disappear
@purchase_window.appear
return @stage = :purchase
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
@coupons_allowed = KyoShop::COUPON_IDS.include?(@discount_window.item.id)
@purchase_window.discount -= @discount
@discount = @discount_window.item.price
@discount_window.disappear
@purchase_window.appear
discount = @purchase_window.discount += @discount
@purchase_window.refresh
text = sprintf(KyoShopLabels::APPLYDISCOUNT, discount)
@question_window.set_text(text)
@stage = :purchase
end
end
def update_appraisal
@appraise_item_window.update
if Input.trigger?(Input::UP) or Input.trigger?(Input::DOWN)
@appraise_info_window.refresh
return
end
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@appraise_item_window.disappear
@appraise_info_window.visible = false
@result_info_window.visible = false
@result_info_window.contents.clear
@appraise_options.disappear
@dummy_window.visible = true
@command_window.visible = true
@number_window.visible = true
@status_window.visible = true
@option_window.appear
@help_window.set_text("")
return @stage = :option
elsif Input.trigger?(Input::C)
if @appraise_item_window.empty?
return $game_system.se_play($data_system.buzzer_se)
end
$game_system.se_play($data_system.decision_se)
@appraise_options.appear
@stage = :appraise_option
end
end
def update_appraisal_option
@appraise_options.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@appraise_options.disappear
return @stage = :appraise
elsif Input.trigger?(Input::C)
data = KyoShop::APPRAISALS[@shop_id]
price = case @appraise_options.index
when 0 then data[:test_cost]
when 1 then data[:cost]
when 2 then -10
end
if price == -10 or $game_party.gold < price
$game_system.se_play($data_system.buzzer_se)
@appraise_options.disappear
return @stage = :appraise
end
$game_system.se_play($data_system.decision_se)
item = @appraise_item_window.item
$game_party.lose_gold(price)
if rand(100) < data[:rate]
goods = data[:goods]
favors = $game_system.shop_favors[@shop_id]
goods += data[:extras] if data[:help_limit] <= favors
key = goods[rand(goods.size)]
else
key = data[:default]
end
kind, id = retrieve_item(key)
case item.class
when RPG::Item then $game_party.lose_item(item.id, 1)
when RPG::Weapon then $game_party.lose_weapon(item.id, 1)
when RPG::Armor then $game_party.lose_armor(item.id, 1)
end
if data[:target].has_key?(key)
@appraise_options.disappear
@favor_options.appear
@result_info_window.ask_favor(new_item)
@target_item = new_item
@target_key = key
@target_points = data[:target][key]
@haggle_enabled = data[:haggle]
@haggle_max = data[:overprice]
return @stage = :appraise_favor
end
case kind
when 0
new_item = $data_items[id]
$game_party.gain_item(id, 1)
when 1
new_item = $data_weapons[id]
$game_party.gain_weapon(id, 1)
when 2
new_item = $data_armors[id]
$game_party.gain_armor(id, 1)
end
@result_info_window.refresh(new_item)
@appraise_item_window.refresh
@gold_window.refresh
@appraise_options.disappear
@stage = :appraise
end
end
def update_appraisal_favor
@favor_options.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@favor_options.disappear
return @stage = :appraise
elsif Input.trigger?(Input::C)
case @favor_options.index
when 0
if @overprice
$game_system.se_play($data_system.shop_se)
$game_system.shop_favors[@shop_id] += @target_points
price = @overprice
@target_points = nil
else
$game_system.se_play($data_system.decision_se)
price = @target_item.price
end
$game_party.gain_gold(price)
@overprice = @target_item = nil
when 1
unless @haggle_enabled
return $game_system.se_play($data_system.buzzer_se)
end
$game_system.se_play($data_system.decision_se)
@haggle_enabled = nil
@overprice = rand(@haggle_max) + 1
@overprice = 25 if @overprice < 25
@overprice += @target_item.price
@result_info_window.make_offer(@overprice)
return
when 2
$game_system.se_play($data_system.decision_se)
case @target_item.class
when RPG::Item then $game_party.gain_item(@target_item.id, 1)
when RPG::Weapon then $game_party.gain_weapon(@target_item.id, 1)
when RPG::Armor then $game_party.gain_armor(@target_item.id, 1)
end
@target_item = nil
@favor_options.disappear
end
return @stage = :appraise
end
end
def check_number
return number = case @item
when RPG::Item then $game_party.item_number(@item.id)
when RPG::Weapon then $game_party.weapon_number(@item.id)
when RPG::Armor then $game_party.armor_number(@item.id)
end
end
def update_number
@number_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@number_window.disappear
@number_window.reset_multiplier
case @command_window.index
when 0 # buy or place order
if @place_order
@place_order = nil
@order_window.appear
@question_window.set_text(KyoShopLabels::PLACEORDER)
elsif @investment
@investment = nil
@status_window.investment = nil
@option_window.appear
@question_window.visible = false
@status_window.visible = false
@dummy_window.visible = true
else
@purchase_window.appear
discount = @purchase_window.discount
if discount == 0
update_discount_message
else
text = sprintf(KyoShopLabels::APPLYDISCOUNT, discount) + "%"
@question_window.set_text(text)
end
end
when 1 # sell
update_discount_message
@sell_window.appear
@status_window.visible = false
end
@stage = @last_stage
return @last_stage = nil
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.shop_se)
@number_window.disappear
case @command_window.index
when 0 # buy
$game_party.lose_gold(@number_window.number * @price)
number = @number_window.number
if @place_order
update_number_place_order(number)
elsif @investment
update_number_investment(number)
else
update_number_purchase(number)
end
return
when 1 # sell
number = @number_window.number
$game_party.gain_gold(number * (@item.price / 2))
case @item
when RPG::Item then $game_party.lose_item(@item.id, number)
when RPG::Weapon then $game_party.lose_weapon(@item.id, number)
when RPG::Armor then $game_party.lose_armor(@item.id, number)
end
@gold_window.refresh
@sell_window.refresh
@status_window.refresh
@sell_window.appear
@status_window.visible = false
@stage = @last_stage
return @last_stage = nil
end
end
end
def update_number_place_order(number)
steps = $game_party.steps + KyoShopOrders.steps[@order_window.index]
order = [nil, @item.id, number, steps]
order[0] = case @item
when RPG::Item then 0
when RPG::Weapon then 1
when RPG::Armor then 2
end
$game_system.placed_orders[@pack_id] ||= []
$game_system.placed_orders[@pack_id] << order
@pickup_window.deliver($game_system.placed_orders[@pack_id])
@gold_window.refresh
@status_window.refresh
@place_order = nil
@order_window.refresh
@order_window.appear
@question_window.set_text(KyoShopLabels::PLACEORDER)
@stage = :place
end
def update_number_investment(number)
@investment = nil
@status_window.investment = nil
$game_system.shop_shares[@shop_id] += number
update_goods_orders_after_investment
@order_window.deliver($game_system.shop_goods)
@purchase_window.deliver($game_temp.shop_goods)
@gold_window.refresh
@question_window.visible = false
@status_window.visible = false
@dummy_window.visible = true
@number_window.reset_multiplier
@number_window.disappear
@option_window.appear
@stage = :option
end
def update_number_purchase(number)
case @item
when RPG::Item then $game_party.gain_item(@item.id, number)
when RPG::Weapon then $game_party.gain_weapon(@item.id, number)
when RPG::Armor then $game_party.gain_armor(@item.id, number)
end
if @coupons_allowed
@coupons_allowed = nil
$game_party.lose_item(@discount_window.item.id, 1)
update_discount_message
@discount_window.refresh
@purchase_window.discount = 0
@discount = 0
end
@gold_window.refresh
@status_window.refresh
@purchase_window.refresh
@purchase_window.appear
@stage = :purchase
end
end
I don't know why I let wulfo convince me of adding such a weird feature, namely the haggling part... =_=
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!
Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!
Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE