Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Adding in a "shop" option to the main menu

Script Title:
Shop menu option add-on

Detailed Description:
So, I'm not too familiar with how Ruby works, but this seems like a fairly simple script to make. What I like is essentially a script that allows me to add another option to the menu and make it to that clicking it will allow me to use an event command. What my actual intention is, is to be able to basically allow the player to call the shop whenever they want, though if it's possible to link it to the shop, then it should be customizable so that I can link a menu option to any event command, right? While I don't have any immediate need for anything other than a shop, the ability to customize the script for other commands will likely come in handy.

As for other scripts I have, I only have a party changer, and that added an option the menu, so I know it's possible to do that. Thank you so much to anyone who can help me out.
 
Your Party Changer script probably overwrites Scene_Menu, so you will need to post the Scene_Menu you are using, or a link to the party changer script so the Shop option can be added to the menu.
 
I've got a bunch of scripts that combine for my party changer, and I'm not sure what's relevant, so I'll post them all.

Game_Party:

Code:
class Game_Party

  

  Max_Party = 5

  

  def max_party

    return Max_Party

  end

  

  def add_actor(actor_id)

    actor = $game_actors[actor_id]

    if not @actors.include?(actor) and $game_party.actors.size < Max_Party

      @actors.push(actor)

      $game_player.refresh

    end

  end

end

 

 

class Window_BattleStatus < Window_Base

  

  def initialize

    super(0, 320, 640, 160)

    self.contents = Bitmap.new(width - 32, height - 32)

    unless $game_party.actors.size > 4

      @level_up_flags = [false, false, false, false]

    else

      @level_up_flags = []

      for i in 0...$game_party.actors.size

        @level_up_flags.push(false)

      end

    end

    refresh

  end

  

  def refresh

    self.contents.clear

    @item_max = $game_party.actors.size

    for i in 0...$game_party.actors.size

      actor = $game_party.actors[i]

      unless $game_party.actors.size > 4

        actor_x = i * 160 + 4

      else

        actor_x = i * (120)

      end

      draw_actor_name(actor, actor_x, 0)

      draw_actor_hp(actor, actor_x, 32, 120)

      draw_actor_sp(actor, actor_x, 64, 120)

      if @level_up_flags[i]

        self.contents.font.color = normal_color

        self.contents.draw_text(actor_x, 96, 120, 32, "LEVEL UP!")

      else

        draw_actor_state(actor, actor_x, 96)

      end

    end

  end

end

 

 

class Game_Actor < Game_Battler

  def screen_x

    if self.index != nil

      unless $game_party.actors.size > 4

        return self.index * 160 + 80

      else

        return self.index * (640/ $game_party.actors.size) + (80/($game_party.actors.size/2))

      end

    else

      return 0

    end

  end

end

 

 

class Scene_Battle

  def phase3_setup_command_window

    @party_command_window.active = false

    @party_command_window.visible = false

    @actor_command_window.active = true

    @actor_command_window.visible = true

    unless $game_party.actors.size > 4

      @actor_command_window.x = @actor_index * 160

    else

      @actor_command_window.x = @actor_index * (640/$game_party.actors.size)

      if @actor_command_window.x > 480

        @actor_command_window.x = 480

      end

    end

    @actor_command_window.index = 0

  end

end

 

class Window_MenuStatus < Window_Selectable

  

  def initialize

    unless $game_party.actors.size > 4

      super(0, 0, 480, 480)

    else

      super(0, 0, 480, 160 * $game_party.actors.size)

    end

    self.contents = Bitmap.new(width - 32, height - 32)

    refresh

    self.active = false

    self.index = -1

  end

  

  alias large_refresh refresh

  def refresh

    large_refresh

    self.height = 480

  end

  

  def update_cursor_rect

    if @index < 0

      self.cursor_rect.empty

      return

    end

    row = @index / @column_max

    if row < self.top_row

      self.top_row = row

    end

    if row > self.top_row + (self.page_row_max - 1)

      self.top_row = row - (self.page_row_max - 1)

    end

    cursor_width = self.width / @column_max - 32

    x = @index % @column_max * (cursor_width + 32)

    y = @index / @column_max * 116 - self.oy

    self.cursor_rect.set(x, y, cursor_width, 96)

  end

  

  def top_row

    return self.oy / 116

  end

  

  def top_row=(row)

    if row < 0

      row = 0

    end

    if row > row_max - 1

      row = row_max - 1

    end

    self.oy = row * 116

  end

  

  def page_row_max

    return 4

  end

end

 

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

# ** Spriteset_Battle

#------------------------------------------------------------------------------

#  This class brings together battle screen sprites. It's used within

#  the Scene_Battle class.

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

 

class Spriteset_Battle

  #--------------------------------------------------------------------------

  # * Public Instance Variables

  #--------------------------------------------------------------------------

  attr_reader   :viewport1                # enemy viewport

  attr_reader   :viewport2                # actor viewport

  #--------------------------------------------------------------------------

  # * Object Initialization

  #--------------------------------------------------------------------------

  def initialize

    # Make viewports

    @viewport1 = Viewport.new(0, 0, 640, 320)

    @viewport2 = Viewport.new(0, 0, 640, 480)

    @viewport3 = Viewport.new(0, 0, 640, 480)

    @viewport4 = Viewport.new(0, 0, 640, 480)

    @viewport2.z = 101

    @viewport3.z = 200

    @viewport4.z = 5000

    # Make battleback sprite

    @battleback_sprite = Sprite.new(@viewport1)

    # Make enemy sprites

    @enemy_sprites = []

    for enemy in $game_troop.enemies.reverse

      @enemy_sprites.push(Sprite_Battler.new(@viewport1, enemy))

    end

    # Make actor sprites

    

    

    @actor_sprites = []

    #@actor_sprites.push(Sprite_Battler.new(@viewport2))

    #@actor_sprites.push(Sprite_Battler.new(@viewport2))

    #@actor_sprites.push(Sprite_Battler.new(@viewport2))

    #@actor_sprites.push(Sprite_Battler.new(@viewport2))

    

    

    for i in 0...$game_party.max_party

      @actor_sprites.push(Sprite_Battler.new(@viewport2))

    end

    

    

    

    # Make weather

    @weather = RPG::Weather.new(@viewport1)

    # Make picture sprites

    @picture_sprites = []

    for i in 51..100

      @picture_sprites.push(Sprite_Picture.new(@viewport3,

        $game_screen.pictures[i]))

    end

    # Make timer sprite

    @timer_sprite = Sprite_Timer.new

    # Frame update

    update

  end

  #--------------------------------------------------------------------------

  # * Frame Update

  #--------------------------------------------------------------------------

  def update

    # Update actor sprite contents (corresponds with actor switching)

    #@actor_sprites[0].battler = $game_party.actors[0]

    #@actor_sprites[1].battler = $game_party.actors[1]

    #@actor_sprites[2].battler = $game_party.actors[2]

    #@actor_sprites[3].battler = $game_party.actors[3]

    

    for i in 0...$game_party.max_party

      @actor_sprites[i].battler = $game_party.actors[i]

    end

    

    # If battleback file name is different from current one

    if @battleback_name != $game_temp.battleback_name

      @battleback_name = $game_temp.battleback_name

      if @battleback_sprite.bitmap != nil

        @battleback_sprite.bitmap.dispose

      end

      @battleback_sprite.bitmap = RPG::Cache.battleback(@battleback_name)

      @battleback_sprite.src_rect.set(0, 0, 640, 320)

    end

    # Update battler sprites

    for sprite in @enemy_sprites + @actor_sprites

      sprite.update

    end

    # Update weather graphic

    @weather.type = $game_screen.weather_type

    @weather.max = $game_screen.weather_max

    @weather.update

    # Update picture sprites

    for sprite in @picture_sprites

      sprite.update

    end

    # Update timer sprite

    @timer_sprite.update

    # Set screen color tone and shake position

    @viewport1.tone = $game_screen.tone

    @viewport1.ox = $game_screen.shake

    # Set screen flash color

    @viewport4.color = $game_screen.flash_color

    # Update viewports

    @viewport1.update

    @viewport2.update

    @viewport4.update

  end

end

Scene_ChangeParty

Code:
class Scene_ChangeParty

# ------------------

def initialize(max_size)

  @max_size = max_size

end

# ------------------

def main

  @left_window = Window_ChangeMain.new

  @right_window = Window_ChangeReserve.new

  @info_window = Window_PartyChangeInfo.new(@max_size)

  @left_window.index = 0

  @right_window.index = -1

  @left_window.active = true

  @right_window.active = false

  @actor1 = nil

  @actor2 = nil

  Graphics.transition

  loop do

    Graphics.update

    Input.update

    update

    if $scene != self

      break

    end

  end

  $game_map.refresh

  Graphics.freeze

  @left_window.dispose

  @right_window.dispose

  @info_window.dispose

end

# ------------------

def update

  @left_window.update

 

  @right_window.update

  @info_window.update

  if @left_window.active

    update_left

    return

  end

  if @right_window.active

    update_right

    return

  end

end

# ------------------

def update_left

  if Input.trigger?(Input::B)

    $game_system.se_play($data_system.cancel_se)

    $scene = Scene_Map.new

    return

  end

  if Input.trigger?(Input::C)

    place = @left_window.index

      if @max_size > 0

        if place >= @max_size

          $game_system.se_play($data_system.buzzer_se)

          return

        end

      end

    if $game_party.actors[place] != nil

      if $game_party.actors[place].required

        $game_system.se_play($data_system.buzzer_se)

        return

      end

    end

    if $game_party.reserve_actors.size == 0

      $game_system.se_play($data_system.decision_se)

      $game_party.transfer_to_reserve($game_party.actors[place])

      @left_window.refresh

      @right_window.refresh

      return

    end

    if $game_party.reserve_actors.size > 0

      $game_system.se_play($data_system.decision_se)

      @left_window.active = false

      @right_window.index = 0

      @right_window.active = true

      @actor1 = $game_party.actors[place]

    return

    end

  end

end

# ------------------

def update_right

  if Input.trigger?(Input::B)

    $game_system.se_play($data_system.cancel_se)

    @right_window.index = -1

    @right_window.active = false

    @left_window.active = true

    return

  end

  if Input.trigger?(Input::C)

    place = @right_window.index

    if place == $game_party.reserve_actors.size

      if @actor1 == nil

        $game_system.se_play($data_system.buzzer_se)

        return

      end

      $game_system.se_play($data_system.decision_se)

      $game_party.transfer_to_reserve(@actor1)

      @right_window.index = -1

      @right_window.active = false

      @left_window.active = true

      @left_window.refresh

      @right_window.refresh

      return

    end

    if @actor1 == nil

      $game_system.se_play($data_system.decision_se)

      @actor2 = $game_party.reserve_actors[place]

      $game_party.transfer_to_party(@actor2)

      @right_window.index = -1

      @right_window.active = false

      @left_window.active = true

      @left_window.refresh

      @right_window.refresh

      return

    else

      @actor2 = $game_party.reserve_actors[place]

      $game_system.se_play($data_system.decision_se)

      $game_party.swap(@actor1, @actor2)

      @right_window.index = -1

      @right_window.active = false

      @left_window.active = true

      @left_window.refresh

      @right_window.refresh

    end

  end

end

# ------------------

end

Window_PartyChangeInfo (Doubt this one's necessary, but posting it anyway)

Code:
class Window_PartyChangeInfo < Window_Base

# ------------------

attr_reader  :max_size

# ------------------

def initialize(max_size)

  super(320, 360, 320, 120)

  self.contents = Bitmap.new(width - 32, height - 32)

  @max_size = max_size

  refresh

end

# ------------------

def refresh

  self.contents.clear

  self.contents.font.name = "Arial"

  self.contents.font.size = 24

  text1 = "Please form a party."

  text2 = "Please form a party"

  text3 = "of up to " + @max_size.to_s + " members."

  if @max_size < 0

    print("Warning: Invalid max size for party.")

    exit

  end

  if @max_size == 0

    self.contents.draw_text(4, 0, 240, 32, text1)

  end

  if @max_size > 0

    self.contents.draw_text(4, 0, 240, 32, text2)

    self.contents.draw_text(4, 32, 240, 32, text3)

  end

end

# ------------------

end

Window_ChangeMain

Code:
class Window_ChangeMain < Window_Selectable

# ---------------------

def initialize

  super(0, 0, 320, 480)

  self.contents = Bitmap.new(width - 32, height - 32)

  refresh

  self.active = false

  self.index = -1

end

# ---------------------

def refresh

  self.contents.clear

  self.contents.font.name = "Arial"

  self.contents.font.size = 24

  @item_max = 4

  for i in 0..3

    x = 64

    y = i * 116

    if $game_party.actors[i] != nil

      actor = $game_party.actors[i]

    else

      self.contents.draw_text(0, y + 32, 288, 32, "-Empty-", 1)

      next

    end

    draw_actor_graphic(actor, x - 40, y + 80)

    draw_actor_name(actor, x, y)

    draw_actor_level(actor, x + 160, y)

    draw_actor_hp(actor, x, y + 32)

    draw_actor_sp(actor, x, y + 64)

  end

end

# ---------------------

def update_cursor_rect

  if @index < 0

    self.cursor_rect.empty

  else

    self.cursor_rect.set(0, @index * 116, self.width - 32, 96)

  end

end

# ---------------------

end

Window_ChangeReserve:

Code:
class Window_ChangeReserve < Window_Selectable

# ---------------------

def initialize

  super(320, 0, 320, 360)

  self.contents = Bitmap.new(width - 32, height - 32)

  refresh

  self.active = false

  self.index = -1

end

# ---------------------

def refresh

  @item_max = $game_party.reserve_actors.size + 1

  size = 96 + @item_max * 96 - 32

  if size < 328

    size = 328

  end

  self.contents.dispose

  self.contents = Bitmap.new(width - 32, size)

  self.contents.clear

  self.contents.font.name = "Arial"

  self.contents.font.size = 24

  for i in 0...$game_party.reserve_actors.size

    x = 64

    y = i * 116

    actor = $game_party.reserve_actors[i]

    draw_actor_graphic(actor, x - 40, y + 80)

    draw_actor_name(actor, x, y)

    draw_actor_level(actor, x + 160, y)

    draw_actor_hp(actor, x, y + 32)

    draw_actor_sp(actor, x, y + 64)

  end

end

# ---------------------

def update_cursor_rect

  if @index < 0

    self.cursor_rect.empty

  else

    self.cursor_rect.set(0, @index * 116 - self.oy, self.width - 32, 96)

  end

  if self.cursor_rect.y < 0

    self.oy -= 116

    refresh

    update_cursor_rect

  end

  if self.cursor_rect.y > 232

    self.oy += 116

    refresh

    update_cursor_rect

  end

end

# ---------------------

end

I know this is a lot of code, and only one or two of them are needed to be altered, but still, it's all here, just in case. And thanks!
 
Oh and I just noticed that a small alteration was made to Scene_Menu. "Leader" was added as a menu option and when it's selected, it does this:

$game_system.se_play($data_system.decision_se)
$scene = Scene_ChangeParty.new(0)
 
EDIT: Ok, I've figured out how to call Scene_Shop. But I'm getting an error that appears to be related to the fact that I have no items for my shop. How can I add items, and also make them change depending on what point you are in the game? (This is my last question I promise.)
 
Ok, since you are asking for help doing this yourself (a good thing! :) ), I'm moving this to support...

Anytime I try to mimic functionality that exists from an event, I look at the code that performs the function from the event. (Interpreter)

Interpreter 2 is the "index" for all of the event commands. The shop command is #302

So, look in Interpreter 6 for command_302

You can see that they are setting $game_temp.shop_calling = true, and
$game_temp.shop_goods = [@parameters]

I just happen to know that [@parameters] is a 2d array, using [type, item_id] to define which goods are available.
So, let's say you have a potion (item, 1), a Bronze Sword (weapon, 1), and a Iron Shield (Armor, 2)

Your statement would be:

$game_temp.shop_goods = [[0, 1],[1, 1],[2, 2]]

You can set this in the initialize method of Scene_Shop (if you are not using any Event driven shops.)
Otherwise, you would have to set it before each visit to the shop.
If your shop just adds new items, and keeps the old ones, you can add items to the array using 'push'

$game_temp.shop_goods.push([0, 2]) ## adds a High Potion to your shop

comprendo?

If you have mixed menu-shop & Event-shop, or you want to set the shop items by level, or based on a variable that represents progress in the game, we can whip up a little piece of code to execute right before calling the shop from your menu.

Be Well
 
Yes, that last thing you mentioned would be perfect!

Basically, I just have the shop option in the menu. I was thinking about having regular ones in towns too, but I realized it would be kind of redundant, much like FFX having inns when the save point healed you. But yeah, some code which can update the shop item list depending on a switch or variable (I think I'm going to do it by chapter number) would be awesome.
 
Well that I can help with methinks, basically what you would need is something like this in your menu script, having a script variable set on which shop you want to be able to be accessed. So 1 for Chapter 1, or something similar to that.
Code:
   

       if $game_switches[1]

      # Play decision SE

      $game_system.se_play($data_system.decision_se)

      # Show the correct shop screen, pending which switch is active

      $game_temp.shop_goods = [@parameters]

      end

      return

    end

 

You could change the shop parameters and switch number, just simply paste it how many ever times you want to change it. Changing the parameters and switch number to what you want.
 
Alright, so I'm not sure how to completely implement your code, Desecration. There might also be an extra End there, not sure. Either way, it seems as though putting it in the menu sets it, but then it just calls scene shop which re-initializes it regardless of chapter. Should the if statement maybe be in scene shop instead? I also need a way to refer to an in-game variable, in the code. That is to say, the variables that you can set with event commands.

But I've got the actual shop itself working.
 
Well aslong as you have a different set of
Code:
if $game_switches[SwitchNumberHere]
and you turn off the previous switch for the last chapter it should work like magic, I'm not quite sure why its causing you a problem. Could you possibly post your script and I'll take a closer look at it, if you like.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top