[XP] Custom Prices

Started by KK20, November 25, 2013, 05:53:22 pm

Previous topic - Next topic

KK20

November 25, 2013, 05:53:22 pm Last Edit: August 23, 2016, 07:07:50 pm by KK20
Custom Prices
Authors: KK20
Version: 1.1
Type: Shop Add-On
Key Term: Custom Shop System



Introduction

RPG Maker only allows items to have one set of prices. The sell price of items is half the price set in the database. With this script, you can modify the prices of items, weapons, and armors to whatever you want. The change is only temporary, so you can have shops sell certain items at unique prices. You can also change the sell price to anything. Make an item cost a high amount, but make it unavailable to sell. Have shops buy specific kinds of items. The choice is up to you!

I made this script because I figured it was simple enough to do and I couldn't find another script that did anything like this.


Features


  • Define new purchase prices for your items, weapons, and armors

  • Use a custom sell price rather than the default "half of item's price"

  • Changes are temporary--reverts prices back to database prices when you close the shop (v1.0)

  • Changes are permanent--carry over in saved games. Only change back when you let them (v1.1)

  • Configure default prices for your items, giving them unique buy/sell prices (v1.1)




Screenshots

None


Demo

None


Script

Spoiler: ShowHide

=begin
===============================================================================
Custom Prices                                                     Version 1.1
by KK20                                                           Aug.23.2016
===============================================================================
_______________________________________________________________________________
+ Introduction

RPG Maker only allows items to have one set of prices. The sell price of items
is half the price set in the database. With this script, you can modify the
prices of items, weapons, and armors to whatever you want. The change is only
temporary, so you can have shops sell certain items at unique prices. You can
also change the sell price to anything. Make an item cost a high amount, but
make it unavailable to sell. Have shops buy specific kinds of items. The
choice is up to you!
_______________________________________________________________________________
+ Instructions

Place this script below the default scripts and above Main, as usual. If you
have any custom save scripts or those that do not alias the "initialize"
method of Game_System, place this script below those.

In the configuration below, you can set the default buy and sell prices for
any of the items. These will ignore the database prices. Instructions are near
the configuration.

To change the prices of items whenever in game, use one of these script calls:

        price(TYPE, ID, BUY_PRICE)
        price(TYPE, ID, BUY_PRICE, SELL_PRICE)
       
  where TYPE can be 0 (Item), 1 (Weapon), or 2 (Armor)
        ID refers to the item's ID in the database
        BUY_PRICE is the new price of the item
        SELL_PRICE is the new sell price of the item
        SELL_PRICE is optional. If you do not put a sell price, items will
          default to being half the BUY_PRICE.
 
  If you ever need to reset the price changes, use the script call:
 
        reset_prices

  It is a good idea to call this method if you only want to change the prices
  of items temporarily, e.g. different shops sell items for various amounts or
  buy specific items only.
       
  -------------     
  Examples:
  -------------
 
  price(0, 1, 300)              # Potion prices: BUY = 300, SELL = 150
  price(1, 1, 5000, 100)        # Bronze Sword prices: BUY = 5000, SELL = 100
  price(2, 25, 9001, 0)         # Ring of Strength prices: BUY = 9001, SELL = Can't sell
_______________________________________________________________________________   
+ Notes

It is recommended to use "price" script calls just before the 'Shop Processing'
command or any other custom shop scripts you may be using.

This script may be compatible with some Custom Shop Systems. The more complex
the script, the less likely.

Changed item prices are permanent until you call "reset_prices" or change them
again with "price" script calls. Any changed prices will be saved in the save
files and be reloaded upon opening the save file.

The biggest change is handling the item's price as a new type of class called
"ItemPrice" rather than as a straight integer. Precautions were made to ensure
that the correct values are used at the appropriate times, but I cannot
guarantee that it is flawless; many of the changes address special cases in the
default RMXP scripts. I only hope that other scripters stuck to these common
practices.

Items that cannot be sold to shops need to have a SELL PRICE of 0.
_______________________________________________________________________________
+ Credits
 
KK20 - for writing the script
firevenge007 - requester

===============================================================================
=end

module CustomPricesConfig
  #------------------------------------------------------------------------
  # Set the default prices of items. The game will use these values instead
  # of the database values as the item's DEFAULT buy and sell prices. Items
  # that do not have a configuration below will use the database prices.
  #
  # Configuration:
  #   when ID then [BUY_PRICE, SELL_PRICE]
  #------------------------------------------------------------------------
  def self.prices(type, id)
    #:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:
    #                                                 START CONFIGURATION
    #:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:
    case type.to_s
    when "RPG::Item"
      case id
      #::::::::::::::::::::::::::::
      when 1 then [200, 75]    # Potion
      when 2 then [500, 300]   # High Potion
      #::::::::::::::::::::::::::::
      end
    when "RPG::Weapon"
      case id
      #::::::::::::::::::::::::::::
      when 1 then [500, 200]   # Bronze Sword
      when 2 then [2500, 1000] # Iron Sword
      #::::::::::::::::::::::::::::
      end
    when "RPG::Armor"
      case id
      #::::::::::::::::::::::::::::
      when 1 then [400, 150]   # Bronze Shield
      when 2 then [2500, 0]    # Iron Shield
      #::::::::::::::::::::::::::::
      end
    end
    #:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:
    #                                                   END CONFIGURATION
    #:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:
  end
end

#==============================================================================
# ** ItemPrice
#------------------------------------------------------------------------------
#  New class for handling custom item prices. Two element array that will be
#  treated as an Integer whenever possible.
#==============================================================================
class ItemPrice
  attr_accessor :prices # [buy_price, sell_price]
 
  def initialize(buy, sell)
    @prices = [buy, sell]
  end

  # Special case: item.price / 2
  # Must consider the sell price instead
  def /(num)
    # If dividing the price by two, must be triggering sell
    num == 2 ? @prices[1] : @prices[0] / num
  end
 
  # Special case: item.price == 0
  # Must consider the sell price instead
  def ==(num)
    num == 0 ? @prices[1] == 0 : @prices[0] == num
  end
 
  def method_missing(name, *args, &block)
    # Special case: item.price > 0
    # Must consider the sell price instead
    if name.id2name == ">" && args[0] == 0
      @prices[1].send(name, *args, &block)
    else
      # Treat the method call like an Integer as much as possible
      @prices[0].send(name, *args, &block)
    end
  end

  def buy_price;  @prices[0]; end
  def sell_price; @prices[1]; end
  def to_s;  @prices[0].to_s; end
 
end
#==============================================================================
# ** Interpreter
#------------------------------------------------------------------------------
#  This interpreter runs event commands. This class is used within the
#  Game_System class and the Game_Event class.
#==============================================================================
class Interpreter
  #--------------------------------------------------------------------------
  # * Set new item prices; save the original prices
  #--------------------------------------------------------------------------
  def price(type, id, buyp, sellp=buyp/2)
    case type
    when 0 # RPG::Item
      # Store the default price of the item, if haven't already
      unless $game_system.original_prices.has_key?($data_items[id])
        $game_system.original_prices[$data_items[id]] = $data_items[id].price
      end
      # Set the item's new price
      $data_items[id].price = ItemPrice.new(buyp, sellp)
      # Store this change so that it gets saved in game
      $game_system.changed_prices[$data_items[id]] = $data_items[id].price
    when 1 # RPG::Weapon
      unless $game_system.original_prices.has_key?($data_weapons[id])
        $game_system.original_prices[$data_weapons[id]] = $data_weapons[id].price
      end
      $data_weapons[id].price = ItemPrice.new(buyp, sellp)
      $game_system.changed_prices[$data_weapons[id]] = $data_weapons[id].price
    when 2 # RPG::Armor
      unless $game_system.original_prices.has_key?($data_armors[id])
        $game_system.original_prices[$data_armors[id]] = $data_armors[id].price
      end
      $data_armors[id].price = ItemPrice.new(buyp, sellp)
      $game_system.changed_prices[$data_armors[id]] = $data_armors[id].price
    else
      return false
    end
    return true
  end
  #--------------------------------------------------------------------------
  # * Revert items back to their original database/configured prices
  #--------------------------------------------------------------------------
  def reset_prices
    $game_system.original_prices.each_pair{|item, price|
      case item.class.to_s
      when "RPG::Item"   then $data_items[item.id].price   = price
      when "RPG::Weapon" then $data_weapons[item.id].price = price
      when "RPG::Armor"  then $data_armors[item.id].price  = price
      end
    }
    $game_system.original_prices.clear
    $game_system.changed_prices.clear
  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
  attr_accessor :original_prices, :changed_prices
  #--------------------------------------------------------------------------
  # * Initialize hash for memorizing base prices
  #--------------------------------------------------------------------------
  alias init_changed_item_prices initialize
  def initialize
    init_changed_item_prices
    @original_prices = {}
    @changed_prices = {}
    set_configured_prices
  end
  #--------------------------------------------------------------------------
  # * Initialize prices based on user's configuration
  #--------------------------------------------------------------------------
  def set_configured_prices
    return if @configured_prices_set
    $data_items.each_index{|index|
      next if index == 0
      item = $data_items[index]
      prices = CustomPricesConfig.prices(item.class, item.id)
      next if prices.nil?
      $data_items[index].price = ItemPrice.new(*prices)
    }
    $data_weapons.each_index{|index|
      next if index == 0
      item = $data_weapons[index]
      prices = CustomPricesConfig.prices(item.class, item.id)
      next if prices.nil?
      $data_weapons[index].price = ItemPrice.new(*prices)
    }
    $data_armors.each_index{|index|
      next if index == 0
      item = $data_armors[index]
      prices = CustomPricesConfig.prices(item.class, item.id)
      next if prices.nil?
      $data_armors[index].price = ItemPrice.new(*prices)
    }
    @configured_prices_set = true
  end
  #--------------------------------------------------------------------------
  # * Restore changed prices from saved game
  #--------------------------------------------------------------------------
  def restore_changed_prices
    @changed_prices.each_key{|item|
      case item.class.to_s
      when "RPG::Item"   then $data_items[item.id].price   = item.price
      when "RPG::Weapon" then $data_weapons[item.id].price = item.price
      when "RPG::Armor"  then $data_armors[item.id].price  = item.price
      end
    }
  end
 
end
#==============================================================================
# ** Scene_Load
#------------------------------------------------------------------------------
#  This class performs load screen processing.
#==============================================================================
class Scene_Load < Scene_File
  # Ensure that the script can work with saved games
  alias create_changed_prices read_save_data
  def read_save_data(file)
    create_changed_prices(file)
    $game_system.changed_prices ||= {}
    $game_system.original_prices ||= {}
    $game_system.set_configured_prices
    $game_system.restore_changed_prices
  end
end

Version 1.0


Instructions

In script. Script calls are

price(TYPE, ID, BUY_PRICE)
price(TYPE, ID, BUY_PRICE, SELL_PRICE)
reset_prices



Compatibility

May be compatible with some Custom Shop Systems. The more exotic, the less likely.
Should work fine with most other scripts.


Credits and Thanks


  • KK20 - for script

  • firevenge007 - for requesting




Author's Notes

Want to make a list of scripts this is/isn't compatible with? Post your results!

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Heretic86

There is another script out there that tries to do something similar, but by comparison, just flat out SUCKS.  Having Total Control over the Prices at each Shop is a fantastic idea.

+Rep
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

KK20

Ah, I see what you meant with that post in your demo collections. The similar script has less features and relies on the SDK.
Glad you think it's a good idea :)

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Heretic86

When I recover from my burnout, would you mind if I include this script in the "Collection" Demo?  You'll be credited, of course, and I want to get rid of ALL SDK dependancies while either maintaining or increasing functionality.
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

KK20

Of course. I see no harm done.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Anasky

First off, sorry for the necropost.

Is there any way to set certain global prices, and only change specific ones for certain shops?

Example:
I want all my items to give 25% of the value when sold, and at a specific shop I want the gardening seeds to cost half the price.

Thanks in advance :)
Anasky


KK20

Script calls would probably look something like this:

for i in 1..$data_items.size
buy_price = $data_items[i].price
price(0, i, buy_price, buy_price / 4)
end
for i in 1..$data_weapons.size
buy_price = $data_weapons[i].price
price(1, i, buy_price, buy_price / 4)
end
for i in 1..$data_armors.size
buy_price = $data_armors[i].price
price(2, i, buy_price, buy_price / 4)
end


for i in STARTING_SEED_INDEX..LAST_SEED_INDEX
buy_price = $data_items[i].price
price(0, i, buy_price / 2)
end

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

KK20

Update to 1.1

Changes have been made to make the script a bit more compatible with custom shop systems.
Uses an entirely new architecture for changing items' prices (mainly to address the above).
Changes are now carried over in save files. Prices no longer reset after leaving a shop.
Added default price configuration option.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Heretic86

I updated the Collection also since I just put in version 1.0.  Now it contains version 1.1 of this script.  Thank you for supporting your scripts and fixing bugs when found as well as adding features.

NOTE: I did have to start a New Game to prevent a script error with "has_key?" which may cause script users to scratch their heads.  That is fairly typical with many scripts.  Installing a new script and using a current save game can cause a lot of errors during development so it is recommended for pretty much any script installation to start a New Game.
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

KK20

Oh whoops forgot a line. Script should work with saved games now.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!