Game Stores Por Astro_mech [RMXP]

10 de setembro de 2012

Game_Stores é um script desenvolvido por Astro_mech, para ser usado em um jogo ou projeto do RPG Maker XP.

Basicamente, este script permite lojas dinâmicas no seu projeto. É muito interessante: além de estoque nas lojas, o preço dos ítens podem subir ou diminuir, dependendo de quanto você compra ou vende.

O Phylomortis.com criou a janela de loja avançada e a demo por KaotiX.

Instruções

Para instalar o script, basta copiar o código abaixo acima do Main.

Para criar uma loja dinâmica, basta criar um evento e chamar o script create_store("ID"), onde ID é algo que identifique a loja (pode usar o nome da loja, por exemplo), e deve estar entre aspas.

Depois crie um comentário com um número. Este número representa, em segundos, o tempo em que a loja atualiza seu estoque. Se você colocar 60, vai demorar 60 segundos, ou um minuto para isto ocorrer.

Daí você vai ter que colocar um comentário para cada item que você quer que tenha na loja. Cada linha contém 6 números, separados por espaço: TIPO ID ESTOQUE PREÇO_MÍNIMO PORCENTAGEM_PREÇO AUMENTO_ESTOQUE?

  • No TIPO, você colocará a natureza do item, 0 para itens, 1 armas e 2 para armaduras
  • No ID, você vai colocar a ID do item, que você acha na sua Database do RMXP mesmo
  • No ESTOQUE, você vai colocar a quantidade disponível, inicial, pra cada item
  • No PREÇO_MÍNIMO, você vai definir o preço inicial mínimo, que pode aumentar dependendo de quanto você compre dele
  • Em PORCENTAGEM_PREÇO, você deve digitar a porcentagem que o preço vai aumentar, cada vez que o item é comprado. Se o preço inicial for 100, e você colocar 1%, vai aumentar 10.
  • Em AUMENTO_ESTOQUE? você define se o estoque vai ser reposto (1) ou não (0).

Estas informações estão também (em inglês) em um dos NPCs da demo.

Código

#==============================================================================
# ■ Game_Stores by Astro_mech
# Special thanks to Phylomortis.com for the advanced shop display window!
#==============================================================================

class Game_Stores
 #--------------------------------------------------------------------------
 def initialize
   @stores = {}
 end
 #--------------------------------------------------------------------------
 def [](id)
   return @stores[id]
 end
 #--------------------------------------------------------------------------
 def create!(items, id, rate)
   @stores[id] = Store.new(items, id, rate)
 end

#==============================================================================

class Store
 #--------------------------------------------------------------------------
 def initialize(items, id, rate)
   #[id, max_stock, now_stock, price_min, price_factor, original_stock?, stock_increase?]
   @items = items[0]
   @weapons = items[1]
   @armors = items[2]
   @id = id
   @restock_rate = rate
   @last_time = Graphics.frame_count / Graphics.frame_rate
 end
 #--------------------------------------------------------------------------
 def get_stock_max(kind, id)
   stock = eval("@" + kind + "s[id][1]")
   return stock
 end
 #--------------------------------------------------------------------------
 def get_stock_now(kind, id)
   stock = eval("@" + kind + "s[id][2]")
   return stock
 end
 #--------------------------------------------------------------------------
 def get_price_min(kind, id)
   factor = eval("@" + kind + "s[id][3]")
   return factor
 end
 #--------------------------------------------------------------------------
 def get_price_factor(kind, id)
   factor = eval("@" + kind + "s[id][4]")
   return factor
 end
 #--------------------------------------------------------------------------
 def get_price_now(kind, id)
   factor = get_price_factor(kind, id).to_f
   price = get_price_min(kind, id).to_f
   times = get_stock_max(kind, id) - get_stock_now(kind, id)
   if times > 0
     times.times do
       price *= (1.0 + factor/100.0)
     end
   elsif times < 0
     times.abs.times do
       price = price - price*(factor/100.0)
     end
   end
   return [[price, 9999999.0].min, 0.0].max.round
 end
 #--------------------------------------------------------------------------
 def update_stock
   if @last_time + @restock_rate < Graphics.frame_count / Graphics.frame_rate
     times = (Graphics.frame_count/Graphics.frame_rate)-(@last_time + @restock_rate)
     times = (times.to_f/@restock_rate.to_f).floor
     @last_time = Graphics.frame_count / Graphics.frame_rate
     for i in 0..times
       self.all_items.each do |item|
         if item[2] < item[1]
           item[2] += 1 if item[6]
         elsif item[2] > item[1]
           item[2] -= 1 if item[6]
         end
       end
     end
     for item in @items.values
       if item[2] <= 0
         item[2] = 0
         @items.delete(item[0]) unless item[5]
       end
     end
     for item in @weapons.values
       if item[2] <= 0
         item[2] = 0
         @weapons.delete(item[0]) unless item[5]
       end
     end
     for item in @armors.values
       if item[2] <= 0
         item[2] = 0
         @armors.delete(item[0]) unless item[5]
       end
     end
     return true
   end
   return false
 end  
 #--------------------------------------------------------------------------
 def all_items
   return @items.values+@weapons.values+@armors.values
 end
 #--------------------------------------------------------------------------
 def stock_items
   return [@items.keys, @weapons.keys, @armors.keys]
 end
 #--------------------------------------------------------------------------
 def increment_stock(kind, id, n)
   if eval("@" + kind + "s[id] != nil")
     eval("@" + kind + "s[id][2] += #{n}")
   else
     add_item(kind, id, n)
   end
 end
 #--------------------------------------------------------------------------
 def decrement_stock(kind, id, n)
   if eval("@" + kind + "s[id] != nil")
     a = eval("@" + kind + "s[id]")
     a[2] = [a[2] - n, 0].max
     if a[2] == 0 and not a[5]
       hash = eval("@" + kind + "s")
       hash.delete(a[0])
     end      
   end
 end
 #--------------------------------------------------------------------------
 def add_item(kind, id, n)
   eval("@" + kind + "s[#{id}] = [#{id}, 0, #{n}, $data_#{kind}s[#{id}].price, 10, false, true]")
 end
 #--------------------------------------------------------------------------
 def has_item?(kind, id)
   return eval("@" + kind + "s.key?(id)")
 end
end

end

#==============================================================================
# ■ Scene_Shop
#==============================================================================

class Scene_Shop
 #--------------------------------------------------------------------------
 def main
   @store = $game_temp.shop_goods
   @store.update_stock
   @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)
   @buy_window = Window_ShopBuy.new(@store)
   @buy_window.active = false
   @buy_window.visible = false
   @buy_window.help_window = @help_window
   @sell_window = Window_ShopSell.new(@store)
   @sell_window.active = false
   @sell_window.visible = false
   @sell_window.help_window = @help_window
   @status_window = Window_ShopStatus.new
   @status_window.visible = false
   Graphics.transition
   loop do
     Graphics.update
     Input.update
     update
     if $scene != self
       break
     end
   end
   Graphics.freeze
   @help_window.dispose
   @command_window.dispose
   @gold_window.dispose
   @dummy_window.dispose
   @buy_window.dispose
   @sell_window.dispose
   @status_window.dispose
 end
 #--------------------------------------------------------------------------
 def update
   @help_window.update
   @command_window.update
   @gold_window.update
   @dummy_window.update
   @buy_window.update
   @sell_window.update
   @status_window.update
   if @store.update_stock
     @buy_window.refresh
     @sell_window.refresh
   end
   if @command_window.active
     update_command
     return
   end
   if @buy_window.active
     update_buy
     return
   end
   if @sell_window.active
     update_sell
     return
   end
 end
 #--------------------------------------------------------------------------
 def update_command
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     $scene = Scene_Map.new
     return
   end
   if Input.trigger?(Input::C)
     case @command_window.index
     when 0
       $game_system.se_play($data_system.decision_se)
       @command_window.active = false
       @dummy_window.visible = false
       @buy_window.active = true
       @buy_window.visible = true
       @buy_window.refresh
       @status_window.visible = true
     when 1
       $game_system.se_play($data_system.decision_se)
       @command_window.active = false
       @dummy_window.visible = false
       @sell_window.active = true
       @sell_window.visible = true
       @sell_window.refresh
       @status_window.visible = true
     when 2  
       $game_system.se_play($data_system.decision_se)
       $scene = Scene_Map.new
     end
     return
   end
 end
 #--------------------------------------------------------------------------
 def update_buy
   @status_window.item = @buy_window.item
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     @command_window.active = true
     @dummy_window.visible = true
     @buy_window.active = false
     @buy_window.visible = false
     @buy_window.index = 0
     @status_window.visible = false
     @status_window.item = nil
     @help_window.set_text("")
     return
   end
   if Input.trigger?(Input::C)
     @item = @buy_window.item
     case @item
     when RPG::Item
       number = $game_party.item_number(@item.id)
       string = "item"
     when RPG::Weapon
       number = $game_party.weapon_number(@item.id)
       string = "weapon"
     when RPG::Armor
       number = $game_party.armor_number(@item.id)
       string = "armor"
     end
     stock = @store.get_stock_now(string, @item.id)
     price = @store.get_price_now(string, @item.id)
     gold = $game_party.gold
     if @item == nil or price > gold or stock == 0 or number == 99
       $game_system.se_play($data_system.buzzer_se)
       return
     end
     $game_system.se_play($data_system.shop_se)
     $game_party.lose_gold(price)
     case @item
     when RPG::Item
       $game_party.gain_item(@item.id, 1)
     when RPG::Weapon
       $game_party.gain_weapon(@item.id, 1)
     when RPG::Armor
       $game_party.gain_armor(@item.id, 1)
     end
     @store.decrement_stock(string, @item.id, 1)
     @gold_window.refresh
     @buy_window.refresh
     @status_window.refresh
   end
 end
 #--------------------------------------------------------------------------
 def update_sell
   @status_window.item = @sell_window.item
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     @command_window.active = true
     @dummy_window.visible = true
     @sell_window.active = false
     @sell_window.visible = false
     @sell_window.index = 0
     @status_window.visible = false
     @status_window.item = nil
     @help_window.set_text("")
     return
   end
   if Input.trigger?(Input::C)
     @item = @sell_window.item
     if @item == nil or @item.price == 0
       $game_system.se_play($data_system.buzzer_se)
       return
     end
     $game_system.se_play($data_system.shop_se)
     case @item
     when RPG::Item
       $game_party.lose_item(@item.id, 1)
       string = "item"
     when RPG::Weapon
       $game_party.lose_weapon(@item.id, 1)
       string = "weapon"
     when RPG::Armor
       $game_party.lose_armor(@item.id, 1)
       string = "armor"
     end
     if @store.has_item?(string, @item.id)
       $game_party.gain_gold((@store.get_price_now(string, @item.id).to_f*0.75).round)
     else
       $game_party.gain_gold((eval("$data_#{string}s[#{@item.id}].price").to_f*0.75).round)
     end
     @store.increment_stock(string, @item.id, 1)
     @gold_window.refresh
     @sell_window.refresh
     @status_window.refresh
   end
 end
end

#==============================================================================
# ■ Window_ShopBuy
#==============================================================================

class Window_ShopBuy < Window_Selectable
 #--------------------------------------------------------------------------
 def initialize(store)
   super(0, 128, 368, 352)
   @store = store
   refresh
   self.index = 0
 end
 #--------------------------------------------------------------------------
 def item
   return @data[self.index]
 end
 #--------------------------------------------------------------------------
 def refresh
   if self.contents != nil
     self.contents.dispose
     self.contents = nil
   end
   @data = []
   for i in 0...@store.stock_items.size
     for j in @store.stock_items[i]
       case i
       when 0
         item = $data_items[j]
       when 1
         item = $data_weapons[j]
       when 2
         item = $data_armors[j]
       end
       if item != nil
         @data.push(item)
       end
     end
   end
   @item_max = @data.size
   if @item_max > 0
     self.contents = Bitmap.new(width - 32, row_max * 32)
     self.contents.font.name = $fontface
     self.contents.font.size = $fontsize
     for i in 0...@item_max
       draw_item(i)
     end
   end
 end
 #--------------------------------------------------------------------------
 def draw_item(index)
   item = @data[index]
   case item
   when RPG::Item
     number = $game_party.item_number(item.id)
     string = "item"
   when RPG::Weapon
     number = $game_party.weapon_number(item.id)
     string = "weapon"
   when RPG::Armor
     number = $game_party.armor_number(item.id)
     string = "armor"
   end
   price = @store.get_price_now(string, item.id)
   stock = @store.get_stock_now(string, item.id)
   if price <= $game_party.gold and number < 99 and stock != 0
     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, 180, 32, item.name, 0)
   temp_color = self.contents.font.color.clone
   self.contents.font.color = system_color
   self.contents.font.color.alpha = temp_color.alpha
   self.contents.draw_text(x + 208, y, 32, 32, stock.to_s, 0)
   self.contents.font.color = temp_color
   self.contents.draw_text(x + 240, y, 88, 32, price.to_s, 2)
 end
 #--------------------------------------------------------------------------
 def update_help
   @help_window.set_text(self.item == nil ? "" : self.item.description)
 end
end

#==============================================================================
# ■ Window_ShopSell
#==============================================================================

class Window_ShopSell < Window_Selectable
 #--------------------------------------------------------------------------
 def initialize(store)
   super(0, 128, 368, 352)
   @store = store
   @column_max = 1
   refresh
   self.index = 0
 end
 #--------------------------------------------------------------------------
 def item
   return @data[self.index]
 end
 #--------------------------------------------------------------------------
 def refresh
   if self.contents != nil
     self.contents.dispose
     self.contents = nil
   end
   @data = []
   for i in 1...$data_items.size
     if $game_party.item_number(i) > 0
       @data.push($data_items[i])
     end
   end
   for i in 1...$data_weapons.size
     if $game_party.weapon_number(i) > 0
       @data.push($data_weapons[i])
     end
   end
   for i in 1...$data_armors.size
     if $game_party.armor_number(i) > 0
       @data.push($data_armors[i])
     end
   end
   @item_max = @data.size
   if @item_max > 0
     self.contents = Bitmap.new(width - 32, row_max * 32)
     self.contents.font.name = $fontface
     self.contents.font.size = $fontsize
     for i in 0...@item_max
       draw_item(i)
     end
   end
 end
 #--------------------------------------------------------------------------
 def draw_item(index)
   item = @data[index]
   case item
   when RPG::Item
     number = $game_party.item_number(item.id)
     string = "item"
   when RPG::Weapon
     number = $game_party.weapon_number(item.id)
     string = "weapon"
   when RPG::Armor
     number = $game_party.armor_number(item.id)
     string = "armor"
   end
   if @store.has_item?(string, item.id)
     price = (@store.get_price_now(string, item.id).to_f*0.75).round
     stock = @store.get_stock_now(string, item.id)
   else
     price = (item.price.to_f*0.75).round
     stock = 0
   end
   if price > 0
     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 / @column_max - 32, 32)
   self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
   bitmap = RPG::Cache.icon(item.icon_name)
   opacity = self.contents.font.color == normal_color ? 255 : 128
   self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
   self.contents.draw_text(x + 28, y, 180, 32, item.name, 0)
   temp_color = self.contents.font.color.clone
   self.contents.font.color = system_color
   self.contents.font.color.alpha = temp_color.alpha
   self.contents.draw_text(x + 208, y, 32, 32, stock.to_s, 0)
   self.contents.font.color = temp_color
   self.contents.draw_text(x + 240, y, 88, 32, price.to_s, 2)
 end
 #--------------------------------------------------------------------------
 def update_help
   @help_window.set_text(self.item == nil ? "" : self.item.description)
 end
end

#==============================================================================
# ■ Window_ShopStatus
#==============================================================================

class Window_ShopStatus < Window_Base
 #--------------------------------------------------------------------------
 def initialize
   super(368, 128, 272, 352)
   self.contents = Bitmap.new(width - 32, height - 32)
   self.contents.font.name = $fontface
   self.contents.font.size = $fontsize
   @item = nil
   refresh
 end
 #--------------------------------------------------------------------------
 def refresh
   self.contents.clear
   if @item == nil
     return
   end
   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
   self.contents.font.color = system_color
   self.contents.draw_text(4, 0, 200, 32, "You own:")
   self.contents.font.color = normal_color
   self.contents.draw_text(204, 0, 32, 32, number.to_s, 2)
   if @item.is_a?(RPG::Item)
     return
   end
   for i in 0...$game_party.actors.size
     actor = $game_party.actors[i]
     if actor.equippable?(@item)
       self.contents.font.color = normal_color
     else
       self.contents.font.color = disabled_color
     end
     self.contents.draw_text(4, 64 + 64 * i, 120, 32, actor.name)
     if @item.is_a?(RPG::Weapon)
       item1 = $data_weapons[actor.weapon_id]
     elsif @item.kind == 0
       item1 = $data_armors[actor.armor1_id]
     elsif @item.kind == 1
       item1 = $data_armors[actor.armor2_id]
     elsif @item.kind == 2
       item1 = $data_armors[actor.armor3_id]
     else
       item1 = $data_armors[actor.armor4_id]
     end
     if actor.equippable?(@item)
       if @item.is_a?(RPG::Weapon)
         atk1 = item1 != nil ? item1.atk : 0
         atk2 = @item != nil ? @item.atk : 0
         change = atk2 - atk1
       end
       if @item.is_a?(RPG::Armor)
         pdef1 = item1 != nil ? item1.pdef : 0
         mdef1 = item1 != nil ? item1.mdef : 0
         pdef2 = @item != nil ? @item.pdef : 0
         mdef2 = @item != nil ? @item.mdef : 0
         change = pdef2 - pdef1 + mdef2 - mdef1
       end
       self.contents.draw_text(124, 64 + 64 * i, 112, 32,
         sprintf("%+d", change), 2)
     end
     if item1 != nil
       x = 4
       y = 64 + 64 * i + 32
       bitmap = RPG::Cache.icon(item1.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, item1.name)
     end
   end
 end
 #--------------------------------------------------------------------------
 def item=(item)
   if @item != item
     @item = item
     refresh
   end
 end
end

#==============================================================================
# ■ Scene_Title
#==============================================================================

class Scene_Title
 alias dynamic_stores_new_game command_new_game
 def command_new_game
   $game_stores = Game_Stores.new
   dynamic_stores_new_game
 end
end

#==============================================================================
# ■ Interpreter
#==============================================================================

class Interpreter
 #--------------------------------------------------------------------------
 def create_store(id)
   if $game_stores[id] == nil
     rate = 0
     items = [Hash.new, Hash.new, Hash.new]
     got_rate = false
     loop do
       @index += 1
       if not [108, 408].include?(@list[@index].code)
         @index -= 1
         break
       end
       next if @list[@index].parameters[0].include?("#")
       if @list[@index].code == 108 and not got_rate
         rate = @list[@index].parameters[0].to_i
         got_rate = true
         next
       end
       if [108, 408].include?(@list[@index].code) and got_rate
         a = @list[@index].parameters[0].split(' ')
         for i in 0...a.size
           a[i].strip!
           a[i] = a[i].to_i
         end
         kind = a[0]
         info = [a[1], a[2], a[2], a[3], a[4], true, (a[5]>=1)]
         items[kind][info[0]] = info
       end
     end
     $game_stores.create!(items, id, rate)
   end
   store = $game_stores[id]
   $game_temp.battle_abort = true
   $game_temp.shop_calling = true
   $game_temp.shop_goods = store
 end
end

#==============================================================================
# ■ Scene_Save
#==============================================================================

class Scene_Save
 def write_save_data(file)
   characters = []
   for i in 0...$game_party.actors.size
     actor = $game_party.actors[i]
     characters.push([actor.character_name, actor.character_hue])
   end
   Marshal.dump(characters, file)
   Marshal.dump(Graphics.frame_count, file)
   $game_system.save_count += 1
   $game_system.magic_number = $data_system.magic_number
   Marshal.dump($game_system, file)
   Marshal.dump($game_switches, file)
   Marshal.dump($game_variables, file)
   Marshal.dump($game_self_switches, file)
   Marshal.dump($game_screen, file)
   Marshal.dump($game_actors, file)
   Marshal.dump($game_party, file)
   Marshal.dump($game_troop, file)
   Marshal.dump($game_map, file)
   Marshal.dump($game_player, file)
   Marshal.dump($game_stores, file)
 end
end

#==============================================================================
# ■ Scene_Load
#==============================================================================

class Scene_Load
 def read_save_data(file)
   characters = Marshal.load(file)
   Graphics.frame_count = Marshal.load(file)
   $game_system         = Marshal.load(file)
   $game_switches       = Marshal.load(file)
   $game_variables      = Marshal.load(file)
   $game_self_switches  = Marshal.load(file)
   $game_screen         = Marshal.load(file)
   $game_actors         = Marshal.load(file)
   $game_party          = Marshal.load(file)
   $game_troop          = Marshal.load(file)
   $game_map            = Marshal.load(file)
   $game_player         = Marshal.load(file)
   $game_stores         = Marshal.load(file)
   if $game_system.magic_number != $data_system.magic_number
     $game_map.setup($game_map.map_id)
     $game_player.center($game_player.x, $game_player.y)
   end
   $game_party.refresh
 end
end

Download e ficha técnica

  • Download (clique com o botão esquerdo do mouse ou toque no link)
  • Desenvolvedor, publisher e/ou distribuidor: Astro_mech
  • SO: Windows 98/98SE/Me/2000/XP/Vista/7
  • Tamanho: 189 KB (pacote de instalação e/ou espaço em disco)
  • Licença: Grátis
  • Categoria: Programação XP
  • Tag: RPG Maker XP
  • Adicionado por: LichKing
  • Acessos: 26

Observação: se você gostou deste post ou ele lhe foi útil de alguma forma, por favor considere apoiar financeiramente a Gaming Room. Fico feliz só de ajudar, mas a contribuição do visitante é muito importante para que este site continua existindo e para que eu possa continuar provendo este tipo de conteúdo e melhorar cada vez mais. Acesse aqui e saiba como. Obrigado!

Deixe um comentário

Inscreva-se na nossa newsletter!