- =begin 
- #=============================================================================== 
-  Title: Shop Manager 
-  Author: Tsukihime 
-  Date: Mar 29, 2013 
- -------------------------------------------------------------------------------- 
-  ** Change log 
-  1.5 Mar 29 
-    - added simple shop refreshing on page change. Will need a better solution 
-      since this does not track the state of a shop on a different page 
-  1.4 Mar 13 
-    - fixed bug where common event shops were not handled appropriately when 
-      called through effects 
-  1.3 Mar 1 
-    - Game_ShopGood now determines whether it should be included or enabled 
-    - Two shop options implemented: hidden, disabled 
-  1.2 Feb 25 
-    - fixed issue where common event shops were not handled correctly 
-    - exposed Shop Good variables as readers 
-  1.1 
-    - ShopManager handles shop scene changing depending on the type of shop 
-    - added handling for different "types" of shops 
-    - all goods in a shop can be accessed via shop.shop_goods 
-    - reference to shop added to shop scene 
-    - added support for adding and removing goods from a shop 
-  1.0 Feb 22, 2013 
-    - Initial Release 
- --------------------------------------------------------------------------------    
-  ** Terms of Use 
-  * Free to use in commercial/non-commercial projects 
-  * No real support. The script is provided as-is 
-  * Will do bug fixes, but no compatibility patches 
-  * Features may be requested but no guarantees, especially if it is non-trivial 
-  * Credits to Tsukihime in your project 
-  * Preserve this header 
- -------------------------------------------------------------------------------- 
-  ** Description 
-   
-  This script serves as a base for all shop-related scripts. 
-   
-  This script provides functionality for remember a shop's "state". 
-  Each shop is uniquely identified by a shop ID, and if you visit the same 
-  shop repeatedly, you should see the same settings. 
-   
-  For example, if a shop holds 10 potions, and you bought 5, then you can 
-  expect that the next time you visit the shop, it will only have 5 potions 
-  remaining. 
-   
-  Of course, you will need extra plugins to have that kind of functionality.  
-  Several new classes have been defined for working with shops, and in 
-  particular, shop goods. 
-   
-  In summary: 
-    -more control over your shops 
-    -simple API for developers to write shop-related scripts 
-   
- -------------------------------------------------------------------------------- 
-  ** Usage 
-   
- -------------------------------------------------------------------------------- 
-  ** Developers 
-   
-  Here are some specifications that I have written. 
-   
-  Have a look through each class to see what is available for use. 
-  If you have any suggestions that will improve the base script (ie: this),  
-  I will consider adding them. 
-   
-  -- Shop Manager -- 
-   
-  This module serves are the interface for all shop-related queries. It handles 
-  how shops are stored for you so that it is easy to properly obtain a reference 
-  to a shop. 
-   
-  You should use the Shop Manager whenever possible. 
-   
-  -- Game Shop -- 
-   
-  This script treats a shop as a concrete object. A shop is created the first 
-  time it is accessed, and will be stored with the game for the remainder of 
-  the game. 
-   
-  A very basic shop is provided, which manages what items are available for sale. 
-  All shops are stored in a global Game_Shops hash in $game_shops 
-   
-  -- Shop Type -- 
-   
-  On top of the basic Game_Shop class, you can define your own shops and 
-  associate them with custom scenes specific to those shops. 
-   
-  The Shop Manager only requires you to be consistent with your shop name. 
-  For example, if your shop type is "CraftShop", then you must define a 
-   
-    Game_CraftShop  - the shop object that the shop will be instantiated with 
-    Scene_CraftShop - the scene that will be called when visiting a CraftShop 
-     
-  Users will set a @shop_type attribute in Game_Interpreter to determine 
-  what type of shop should be created 
-   
-  -- Managing shops -- 
-   
-  This script assumes shops are only called through events or common events. 
-  Troop events are not supported. 
-   
-  A shop is identified by a map ID and an event ID. 
-  Shops that are called via common events will have a map ID of 0. 
-   
-  In order to determine whether a normal event or a common event called the 
-  shop, the "depth" of the interpreter is used. 
-   
-     When depth = 0, then it is a normal event 
-     When depth > 0, then it is a common event 
-      
-  The shop processing should be handled appropriately depending on the depth 
-   
-  This script assumes that an event is triggered through "normal" interaction; 
-  that is, you can only interact with events within a map. Any events that should 
-  be treated as the same event should be done as a common event call. 
-   
-  --- Shop Goods --- 
-   
-  Rather than storing all goods as a simple array of values, this script 
-  provides a Game_ShopGood class. You can use this to store any additional 
-  information that you want. 
-   
-  All shop related scenes and windows MUST provide support for handling shop 
-  goods. While backwards compatibility is provided for the default scripts, 
-  additional methods have been defined to allow you to retrieve the currently 
-  selected shop good. 
-   
-  --- Shop Options --- 
-   
-  Since there isn't actually a way to setup individual shop goods, external 
-  approaches must be used. There is not much specification here yet, so it 
-  is up to you how you wish to populate your ShopGood objects. I have provided 
-  a "setup_goods" method in Game_Interpreter that you can alias. 
-   
- -------------------------------------------------------------------------------- 
-  ** Compatibility 
-   
-  This script changes the following from the default scripts 
-   
-    DataManager 
-      aliased  - create_game_objects    
-      aliased  - make_save_contents 
-      aliased  - extract_save_contents 
-    Game_Interpreter 
-      replaced - command_302 
-    Window_ShopBuy 
-      replaced - prepare 
-    Scene_Shop 
-      replaced - make_item_list  
- #=============================================================================== 
- =end 
- $imported = {} if $imported.nil? 
- $imported["TH_ShopManager"] = 1.5 
- #=============================================================================== 
- # ** Rest of the Script 
- #===============================================================================  
-   
- #------------------------------------------------------------------------------- 
- # 作为商店和其他对象之间的界面的主力店经理 
- # ShopManager 的主要作用是本质上是管理店里的任何在游戏中存在的对象 
- # 尤其是,它提供了所有的方法 
- # 创建、 检索和删除商店。 
- # 所有的商店都存储在 全局变量$game_shops 的 Game_Shops哈希表 
- #------------------------------------------------------------------------------- 
- module ShopManager 
-   
-   #----------------------------------------------------------------------------- 
-   # 返回一个引用到一个特定的商店 
-   #----------------------------------------------------------------------------- 
-   def self.get_shop(map_id, event_id) 
-     return $game_shops[map_id, event_id] 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # 表明一家店需要刷新 
-   #----------------------------------------------------------------------------- 
-   def self.refresh_shop(map_id, event_id) 
-     shop = get_shop(map_id, event_id) 
-     shop.need_refresh = true if shop 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # 设置商店,如果第一次访问 
-   #----------------------------------------------------------------------------- 
-   def self.setup_shop(map_id, event_id, goods, purchase_only, shop_type) 
-     shop = get_shop(map_id, event_id) 
-     return shop if shop && !shop.need_refresh 
-     shop = shop_class(shop_type).new(goods, purchase_only) 
-     $game_shops[map_id, event_id] = shop 
-     return shop 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # 返回给定商店类型的适当店类 
-   #----------------------------------------------------------------------------- 
-   def self.shop_class(shop_type) 
-     shop_type = "Game_" + shop_type.to_s 
-     return Object.const_get(shop_type.to_sym) 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # 返回与这家商店关联的场景 
-   # TO DO 
-   #----------------------------------------------------------------------------- 
-   def self.shop_scene(shop) 
-     shop_scene = "Scene_" + shop.class.name.gsub("Game_", "") 
-     return Object.const_get(shop_scene.to_sym) 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # 在适当的舞台上调用 SceneManager.call 
-   #----------------------------------------------------------------------------- 
-   def self.call_scene(shop) 
-   
-     SceneManager.call(shop_scene(shop)) 
-     SceneManager.scene.prepare(shop) 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # 在适当的舞台上调用 SceneManager.goto 
-   #----------------------------------------------------------------------------- 
-   def self.goto_scene(shop) 
-     SceneManager.goto(shop_scene(shop)) 
-     SceneManager.scene.prepare(shop) 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Returns a good ID, given a shop and an item. If the item is already in 
-   # the shop, it will return that good's ID. Otherwise, it will return a new ID 
-   # 给定一个商店和一个项目的情况下返回一个好的 ID。如果该项目已在 
-   # 店里,它将返回货物的 id。否则,它将返回一个新的 ID 
-   #----------------------------------------------------------------------------- 
-   def self.get_good_id(shop, item) 
-     good = shop.shop_goods.detect {|good| good.item == item} 
-     return good.nil? ? shop.shop_goods.size + 1 : good.id 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Returns a good, given a shop and an item. If the shop already has that good 
-   # just return it. Otherwise, make a new good. If the price is negative, then 
-   # the price is the default price. Otherwise, it is the specified price. 
-   # 给定一个商店和一个项目的情况下返回一个货物。如果店里已经有货物 
-   # 只返回它。否则,造就了一个新的货物。如果价格是消极的那么 
-   # 价格是默认价格。否则,它是指定的价格。 
-   #----------------------------------------------------------------------------- 
-   def self.get_good(shop, item, price=-1) 
-     good = shop.shop_goods.detect {|good| good.item == item} 
-     return good if good 
-     good_id = shop.shop_goods.size + 1 
-     type = item_type(item) 
-     if price < 0 
-       price_type = price = 0 
-     else 
-       price_type = 1 
-     end 
-     return Game_ShopGood.new(good_id, type, item.id, price_type, price) 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # 返回的项的类型。 
-   #----------------------------------------------------------------------------- 
-   def self.item_type(item) 
-     return 0 if item.is_a?(RPG::Item) 
-     return 1 if item.is_a?(RPG::Weapon) 
-     return 2 if item.is_a?(RPG::Armor) 
-     return -1 
-   end 
- end 
-   
- #------------------------------------------------------------------------------- 
- # Shops are stored in a global variable `$game_shops`. This is dumped and 
- # loaded appropriately. 
- # 商店都存储在全局变量 '$game_shops'。这是适当的倾倒和加载 
- #------------------------------------------------------------------------------- 
- module DataManager 
-   
-   class << self 
-     alias :th_shop_manager_create_game_objects :create_game_objects 
-     alias :th_shop_manager_make_save_contents :make_save_contents  
-     alias :th_shop_manager_extract_save_contents :extract_save_contents 
-   end 
-   
-   def self.create_game_objects 
-     th_shop_manager_create_game_objects 
-     $game_shops = Game_Shops.new 
-   end 
-   
-   def self.make_save_contents 
-     contents = th_shop_manager_make_save_contents 
-     contents[:shops] = $game_shops 
-     contents 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Load shop data 商店数据加载 
-   #----------------------------------------------------------------------------- 
-   def self.extract_save_contents(contents) 
-     th_shop_manager_extract_save_contents(contents) 
-     $game_shops = contents[:shops] 
-   end 
- end 
-   
- class Game_Temp 
-   
-   # even if we're not actually calling a shop, it shouldn't affect anything 
-   # because we are always setting this at each common event call by an event 
-   attr_accessor :shop_common_event_id 
-   
-   alias :th_shop_manager_reserve_common_event :reserve_common_event 
-   def reserve_common_event(common_event_id) 
-     th_shop_manager_reserve_common_event(common_event_id) 
-     @shop_common_event_id = common_event_id 
-   end 
- end 
-   
- class Game_Event < Game_Character 
-   
-   alias :th_shop_manager_setup_page :setup_page 
-   def setup_page(page) 
-     th_shop_manager_setup_page(page) 
-     ShopManager.refresh_shop(@map_id, @id) 
-   end 
- end 
-   
- class Game_Interpreter 
-   
-   alias :th_shop_manager_clear :clear 
-   def clear 
-     th_shop_manager_clear 
-     clear_shop_options 
-     @shop_type = nil 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # New. 
-   #----------------------------------------------------------------------------- 
-   def clear_shop_options 
-     @shop_options = {} 
-     @shop_options[:hidden] = {} 
-     @shop_options[:disabled] = {} 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # New. We are in a common event only if the shop common event ID is set. 
-   #----------------------------------------------------------------------------- 
-   def shop_map_id 
-     $game_temp.shop_common_event_id ? 0 : @map_id 
-   end 
-   
-   def shop_event_id 
-     $game_temp.shop_common_event_id ? $game_temp.shop_common_event_id : @event_id 
-   end 
-   
-   #-------------------------------------------------------------------------- 
-   # Set the shop's common event ID 
-   #-------------------------------------------------------------------------- 
-   alias :th_shop_manager_command_117 :command_117 
-   def command_117 
-     $game_temp.shop_common_event_id = @params[0] 
-     th_shop_manager_command_117 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Replaced. A shop is setup only once, and is retrieved whenever it is 
-   # called in the future. This assumes the shop is invoked through "normal" 
-   # event interactions. 
-   #----------------------------------------------------------------------------- 
-   def command_302 
-     return if $game_party.in_battle 
-     shop_type = @shop_type || :Shop 
-     good_id = 1 
-     goods = [] 
-   
-     # setup goods 
-     good = make_good(@params[0..-1], good_id) # last param is for the shop 
-     goods.push(good) 
-     good_id +=1 
-   
-     while next_event_code == 605 
-       @index += 1 
-       good = make_good(@list[@index].parameters, good_id) 
-       goods.push(good) 
-       good_id +=1 
-     end 
-     # Setup shop if needed 
-     shop = ShopManager.setup_shop(shop_map_id, shop_event_id, goods, @params[4], shop_type) 
-   
-     # prepare the shop with a reference to the actual shop 
-     ShopManager.call_scene(shop) 
-     Fiber.yield 
-   
-     # clear out the shop common event ID. 
-     $game_temp.shop_common_event_id = nil 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # New. This is where the goods are setup. 
-   #----------------------------------------------------------------------------- 
-   def make_good(goods_array, good_id) 
-     item_type, item_id, price_type, price = goods_array 
-     good = Game_ShopGood.new(good_id, item_type, item_id, price_type, price) 
-   
-     # additional setup 
-     setup_good(good, good_id) 
-     return good 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # New. You can do more things with your good here 
-   #----------------------------------------------------------------------------- 
-   def setup_good(good, good_id) 
-     setup_hidden_option(good, good_id) 
-     setup_disabled_option(good, good_id) 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # New. Shop options 
-   #----------------------------------------------------------------------------- 
-   def hide_good(good_id, condition) 
-     @shop_options[:hidden][good_id] = condition 
-   end 
-   
-   def disable_good(good_id, condition) 
-     @shop_options[:disabled][good_id] = condition 
-   end 
-   
-   def setup_hidden_option(good, good_id) 
-     return unless @shop_options[:hidden][good_id] 
-     good.hidden_condition = @shop_options[:hidden][good_id] 
-   end 
-   
-   def setup_disabled_option(good, good_id) 
-     return unless @shop_options[:disabled][good_id] 
-     good.disable_condition = @shop_options[:disabled][good_id] 
-   end 
- end 
-   
- #------------------------------------------------------------------------------- 
- # A shop good. 
- # This is a wrapper around a raw item (RPG::Item, RPG::Weapon, etc). 
- #------------------------------------------------------------------------------- 
-   
- class Game_ShopGood 
-   
-   attr_reader :id         # ID of this good 
-   attr_reader :item_type 
-   attr_reader :item_id 
-   attr_reader :price_type 
-   attr_accessor :hidden_condition 
-   attr_accessor :disable_condition 
-   
-   def initialize(id, item_type, item_id, price_type, price) 
-     @id = id 
-     @item_type = item_type 
-     @item_id = item_id 
-     @price_type = price_type 
-     @price = price 
-     @hidden_condition = "" 
-     @disable_condition = "" 
-   end 
-   
-   def include? 
-     return false if eval(@hidden_condition) 
-     return true 
-   end 
-   
-   def enable? 
-     return false if eval(@disable_condition) 
-     return true 
-   end 
-   
-   def item 
-     return $data_items[@item_id] if @item_type == 0 
-     return $data_weapons[@item_id] if @item_type == 1 
-     return $data_armors[@item_id] if @item_type == 2 
-   end 
-   
-   def price 
-     return item.price if @price_type == 0 
-     return @price 
-   end 
- end 
-   
- #------------------------------------------------------------------------------- 
- # A shop object. Stores information about the shop such as its inventory 
- # and other shop-related data 
- #------------------------------------------------------------------------------- 
- class Game_Shop 
-   attr_reader :purchase_only 
-   attr_reader :shop_goods      # all goods that this shop has.  
-   attr_accessor :need_refresh  # shop needs to be refreshed 
-   
-   def initialize(goods, purchase_only=false) 
-     @shop_goods = goods 
-     @purchase_only = purchase_only 
-     @need_refresh = false 
-   end 
-   #----------------------------------------------------------------------------- 
-   # Returns true if the goods should be included 
-   #----------------------------------------------------------------------------- 
-   def include?(index) 
-     true 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Return a set of goods for sale 
-   #----------------------------------------------------------------------------- 
-   def goods 
-     @shop_goods 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Add a new good to the shop 
-   #----------------------------------------------------------------------------- 
-   def add_good(good) 
-     @shop_goods.push(good) unless @shop_goods.include?(good) 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Remove the specified good from the shop 
-   #----------------------------------------------------------------------------- 
-   def remove_good(good_id) 
-     @shop_goods.delete_at(good_id - 1) 
-   end 
- end 
-   
- #------------------------------------------------------------------------------- 
- # 包含在游戏中的所有商店的包装。 
- #------------------------------------------------------------------------------- 
- class Game_Shops 
-   
-   #----------------------------------------------------------------------------- 
-   # Initializes a hash of game shops. Each key is a map ID, pointing to another 
-   # hash whose keys are event ID's and values are Game_Shop objects. 
-   # 初始化游戏商店的哈希。每个键是一个地图 ID 指向另一个哈希,那个 
-   # 哈希的键是事件 ID    值是 Game_Shop 对象。 
-   #----------------------------------------------------------------------------- 
-   def initialize 
-     @data = {} 
-   end 
-   
-   def [](i, j) 
-     @data[i] ||= {} 
-     @data[i][j] 
-   end 
-   
-   def []=(i, j, shop) 
-     @data[i] ||= {} 
-     @data[i][j] = shop 
-   end 
- end 
-   
- #------------------------------------------------------------------------------- 
- # The shop scene now works with the Shop and ShopGood objects 
- #------------------------------------------------------------------------------- 
- class Scene_Shop < Scene_MenuBase 
-   #-------------------------------------------------------------------------- 
-   # Replaced. The scene now takes a Game_Shop object 
-   #-------------------------------------------------------------------------- 
-   def prepare(shop) 
-     @shop = shop 
-     @goods = shop.goods 
-     @purchase_only = shop.purchase_only 
-   end 
-   
-   alias :th_shop_manager_on_buy_ok :on_buy_ok 
-   def on_buy_ok 
-     @selected_good = @buy_window.current_good 
-     th_shop_manager_on_buy_ok 
-   end 
- end 
-   
- #------------------------------------------------------------------------------- 
- # @shop_goods is now an array of Game_ShopGoods 
- #------------------------------------------------------------------------------- 
- class Window_ShopBuy < Window_Selectable 
-   
-   #-------------------------------------------------------------------------- 
-   # New. Returns true if the good should be included in the shop inventory 
-   #-------------------------------------------------------------------------- 
-   def include?(shopGood) 
-     shopGood.include? 
-   end 
-   
-   alias :th_shop_manager_enable? :enable? 
-   def enable?(item) 
-     return false unless @goods[item].enable? 
-     th_shop_manager_enable?(item) 
-   end 
-   
-   #-------------------------------------------------------------------------- 
-   # New. Get the currently selected good 
-   #-------------------------------------------------------------------------- 
-   def current_good 
-     @goods[item] 
-   end 
-   
-   #----------------------------------------------------------------------------- 
-   # Replaced. ShopGood takes care of most information. The data still contains 
-   # a list of RPG items for now since I don't want to change them to goods yet 
-   # A separate list of goods for sale is used for 1-1 correspondence 
-   #----------------------------------------------------------------------------- 
-   def make_item_list 
-     @data = [] 
-     @goods = {} 
-     @price = {} 
-     @shop_goods.each do |shopGood| 
-       next unless include?(shopGood) 
-       item = shopGood.item 
-       @data.push(item) 
-       @goods[item] = shopGood 
-       @price[item] = shopGood.price 
-     end 
-   end 
- end