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.

Scripts need minor adjustments

I have these two scripts that Brewmeister brewed for me that have slight issues. First, let me explain what the scripts are supposed to do. One script is a window class that goes with a Scene. The Scene opens a window that contains items that you specify when calling the script through an event command. The player can choose which items he wants by selecting them. The only problem is that the items just stay there after you select them, instead of leaving the scene. They still enter your inventory, but since they don't go away, the player can keep clicking on them infinitely.

I need for the script to get rid of the items that you select and when you exit the scene, the items are still gone once the scene is re-called. Like, if I want the scene to be called with the initial items of A and B, the player will take item A then leave. He then opens it again and only item B is there.

Here's the window script:
Code:
#==============================================================================

# ** Window_Chest

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

#  This window displays items in a chest

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

 

class Window_Chest < Window_Selectable

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

  # * Object Initialization

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

  def initialize(items, weapons, armor)

    super(270, 54, 240, 380)

    @column_max = 1

    @items = items

    @weapons = weapons

    @armor = armor

    refresh

    self.index = 0

    self.back_opacity = 160

    # If in battle, move window to center of screen

    # and make it semi-transparent

    if $game_temp.in_battle

      self.y = 64

      self.height = 256

      self.back_opacity = 160

    end

  end

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

  # * Get Item

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

  def item

    return @data[self.index]

  end

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

  # * Refresh

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

  def refresh

    if self.contents != nil

      self.contents.dispose

      self.contents = nil

    end

    @data = []

    # Add item

    for i in [email=0...@items.size]0...@items.size[/email]

        @data.push($data_items[@items[i]])

    end

    # Add weapons and Armor

    for i in [email=0...@weapons.size]0...@weapons.size[/email]

        @data.push($data_weapons[@weapons[i]])

    end

    for i in [email=0...@armor.size]0...@armor.size[/email]

        @data.push($data_armors[@armor[i]])

    end

    # If item count is not 0, make a bit map and draw all items

    @item_max = @data.size

    if @item_max > 0

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

      for i in 0...@item_max

        draw_item(i)

      end

    end

  end

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

  # * Draw Item

  #     index : item number

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

  def draw_item(index)

    item = @data[index]

    x = 4 + index % 1 * (288 + 32)

    y = index / 1 * 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, 212, 32, item.name, 0)

  end

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

  # * Help Text Update

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

  def update_help

    @help_window.set_text(self.item == nil ? "" : self.item.description)

  end

end

 

and here's the scene script:

Code:
#==============================================================================

# ** Scene_Chest

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

#  This class performs chest screen processing.

#  Call with:

#  $scene = Scene_Chest.new([items],[weapons],[armor])

#  EX:

#  $scene = Scene_Chest.new([1,2,3],[1,2,3],[1,2,3])

#  Use an empty array [] if no object of that type

#  EX:

#  $scene = Scene_Chest.new([1,2,3],[],[1,2,3])

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

 

class Scene_Chest

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

  # * Initialize

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

  def initialize(items, weapons, armor)

    @items = items

    @weapons = weapons

    @armor = armor

  end

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

  # * Main Processing

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

  def main

    # Make menu background

    @spriteset = Spriteset_Map.new

    @item_window = Window_Chest.new(@items, @weapons, @armor)

    # Execute transition

    Graphics.transition

    # Main loop

    loop do

      # Update game screen

      Graphics.update

      # Update input information

      Input.update

      # Frame update

      update

      # Abort loop if screen is changed

      if $scene != self

        break

      end

    end

    # Prepare for transition

    Graphics.freeze

    # Dispose of windows

    @item_window.dispose

  end

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

  # * Frame Update

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

  def update

    # Update windows

    @item_window.update

    update_item

  end

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

  # * Frame Update (when item window is active)

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

  def update_item

    # If B button was pressed

    if Input.trigger?(Input::B)

      # Play buzzer SE

      $game_system.se_play($data_system.buzzer_se)

      # Switch to map screen

      $scene = Scene_Map.new

      return

    end

    # If C button was pressed

    if Input.trigger?(Input::C)

      # Get currently selected data on the item window

      @item = @item_window.item

      # Play decision SE

      $game_system.se_play($data_system.decision_se)

      # Add the item to the inventory

      case @item

      when RPG::Item

        $game_party.gain_item(@item.id, 1)

        # Draw item window item

        @item_window.draw_item(@item_window.index)

      when RPG::Weapon

        $game_party.gain_weapon(@item.id, 1)

        # Draw item window item

        @item_window.draw_item(@item_window.index)

      when RPG::Armor

        $game_party.gain_armor(@item.id, 1)

        # Draw item window item

        @item_window.draw_item(@item_window.index)

      end

    end

  end

end

 

I will be extremely grateful to whoever can help me with this. Thanks.
 
If I remember correctly, the object was to limit the user to only one choice from the chest contents.
i.e. you use a self-switch in the event to prevent them from looting the chest more than once.
If the player can take everything, you might as well just give them everything in the chest.

If the new objective is to let them choose 'some' of the contents (ex: 2 out of 4 items), we could loop when a choice is made, and let them choose additional objects until a 'max' is reached.
then, just give you an additional argument for the 'max' number.

Be Well
 
if you only want to let the user have one chance to grab everything by using a switch i already fixed the code(cleaning it up atm) however, if you want to be able to grab 2 items now and two latter let me know(i already started to set it up then i came back to your post and noticed i might not need it)

edit:i totally just noticed it was brew talking to you, sorry if i stepped on your toes by making my own solution
 
@Plague - The two now and two later sounds perfect. Also, this might be important: the script is called with the event command $scene = Scene_Chest.new([items],[armor],[weapons]) and will be used multiple different times throughout the game.

@Brew - I wanted sort of an OBLIVION type thing, except without the weight limit. Or maybe the 'maximum items' idea you said could act as its own weight system though. I like that idea!
 
Almost! The only thing is that it can only be used once, and if there are multiple chests in the game, they will all magically have the same contents :(.

Would there be a way to assign each chest data to a self variable? or something
 
thats not true at all, give each chest a name.

ChestData::Chests['Chest1']=Chest.new([1],[1],[1])
ChestData::Chests['Chest2']=Chest.new([2],[2],[2])

i can make a demo with tons of chest if you want, so u can see how it would work
 
That's fine Plague, we're all in this together.
I didn't get that he was using an item limit, which makes sense now that you might want to pick a couple items up, and once you use them come back for the rest.

I think I would have designed the system completely different knowing that.
Probably setting the contents of each chest up front in the scripts, then just calling something like $scene = Scene_Chest.new(1) for chest #1
with a chest class, and a ChestData module or class that gets saved.
or, skipping the extra scene altogether, and just have a persistent Window_Chest in Scene_Map that toggles between visible & invisible like the message window.

Be Well
 
just wondering do you have any comments on how i did it? im still trying to learn

[rgss]#==============================================================================
# ** Chest by Plague180
# ** ChestData by Plague180
# ** Data::Object by Sephirothspawn
#------------------------------------------------------------------------------
#  This window displays items in a chest
#==============================================================================
module ChestData
  # Save location for chests
  Chests = {}
  #--------------------------------------------------------------------------
  # * Load
  #--------------------------------------------------------------------------
  def self.load
    filename = "Data/Chest.rxdata"
    file = File.open(filename, "rb")
    Chests.merge!(Marshal.load(file))
    file.close
  end
  #--------------------------------------------------------------------------
  # * Save
  #--------------------------------------------------------------------------
  def self.save
    filename = "Data/Chest.rxdata"
    file = File.open(filename, "wb")
    Marshal.dump(Chests, file)
    file.close
  end
end
#this class was made by seph not me
class Data::Object
  @@ids = {}
  @@containers = {}
  attr_accessor :id
  def initialize
    @@ids[self.class] = 0 unless @@ids.has_key?(self.class)
    @@ids[self.class] += 1
    @id = @@ids[self.class]
    if @@containers.has_key?(self.class)
      @@containers[self.class][@id] = self
    end
  end
  def self.add_container(class_name, container)
    @@containers[class_name] = container
  end
end
# kept simple this class keeps track of chest data
class Chest < Data::Object
  Data::Object.add_container(self, ChestData::Chests)
  attr_accessor :items
  attr_accessor :wep
  attr_accessor :arm
  attr_accessor :data
  def initialize(items,wep,arm)
    super()
    @items = items
    @wep = wep
    @arm = arm
    @data = []
    add_data
  end  
  def add_data
  # Add items to chest data
    for i in 0...@items.size
        @data.push($data_items[@items])
    end
    # Add weapons and Armor chest data
    for i in 0...@wep.size
        @data.push($data_weapons[@wep])
    end
    for i in 0...@arm.size
        @data.push($data_armors[@arm])
      end
    end  
end  
 
[/rgss]
[rgss] 
#==============================================================================
# ** Window_Chest by Brewmeister, modified for Plague180's ChestData
#------------------------------------------------------------------------------
#  This window displays items in a chest
#==============================================================================
 
class Window_Chest < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(data)
    super(270, 54, 240, 380)
    @column_max = 1
    @data = data
    refresh
    self.index = 0
    self.back_opacity = 160
    # If in battle, move window to center of screen
    # and make it semi-transparent
    if $game_temp.in_battle
      self.y = 64
      self.height = 256
      self.back_opacity = 160
    end
  end
  #--------------------------------------------------------------------------
  # * Get Item
  #--------------------------------------------------------------------------
  def item
    return @data[self.index]
  end
  #--------------------------------------------------------------------------
  # * Remove item from chest data
  #--------------------------------------------------------------------------
  def get_item
    # Delete item from chest(@data)
    @data.delete_at(self.index)
    # Remove empty slot
    @data.compact
    # Save changes to chest
    ChestData.save
    # Let player take more items, unless chest is empty, if so return to map
    if @data.size != 0
      refresh
    else
      $scene = Scene_Map.new
    end  
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    # If item count is not 0, make a bit map and draw all items
    @item_max = @data.size
    if @item_max > 0
      self.contents = Bitmap.new(width - 32, row_max * 32)
      for i in 0...@item_max
          draw_item(i)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Item
  #     index : item number
  #--------------------------------------------------------------------------
  def draw_item(index)
    item = @data[index]
    x = 4 + index % 1 * (288 + 32)
    y = index / 1 * 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, 212, 32, item.name, 0)
  end
  #--------------------------------------------------------------------------
  # * Help Text Update
  #--------------------------------------------------------------------------
  def update_help
    @help_window.set_text(self.item == nil ? "" : self.item.description)
  end
end
 
[/rgss]
[rgss]#==============================================================================
# ** Scene_Chest by Brewmeister, modified for Plague180's ChestData
#------------------------------------------------------------------------------
#  This class performs chest screen processing.
#  Create Chest:
#  ChestData::Chests['Chest Name'] = Chest.new([1],[1],[1])
#  Chest.new([items],[weapons],[armor])
#  Empty slots must still have [] EX: Chest.new([1],[],[2])
#  For rore then one item use: Chest.new([1,2,3],[],[])
#  Call with:
#  $scene = Scene_Chest.new('Chest Name')
#==============================================================================
 
class Scene_Chest
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(chest)
    # Load chest data
    ChestData.load
    # Grab chest data
    @chest = ChestData::Chests[chest]
  end
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    # Make menu background
    @spriteset = Spriteset_Map.new
    #Make new chest window
    @item_window = Window_Chest.new(@chest.data)
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of windows
    @item_window.dispose
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Update windows
    @item_window.update
    update_item
  end
  #--------------------------------------------------------------------------
  # * Frame Update (when item window is active)
  #--------------------------------------------------------------------------
  def update_item
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play buzzer SE
      $game_system.se_play($data_system.buzzer_se)
      # Switch to map screen
      $scene = Scene_Map.new
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Get currently selected data on the item window
      @item = @item_window.item
      # Play decision SE
      $game_system.se_play($data_system.decision_se)
      # Remove item from list
      @item_window.get_item
      case @item
      when RPG::Item
        # Add the item to the inventory
        $game_party.gain_item(@item.id, 1)
      when RPG::Weapon
        # Add the weapon to the inventory
        $game_party.gain_weapon(@item.id, 1)
      when RPG::Armor
        # Add the armor to the inventory
        $game_party.gain_armor(@item.id, 1)
      end
    end
  end
end
 
[/rgss]
 
Looks pretty good. I typically wouldn't use "Module". I think of modules as 'common methods that can be used by many other classes' such as Math:: or Graphics::
or as a container to collect related classes & methods. e.g. RPG::
But, this works fine, and I don't think there are any significant drawbacks to using module.

I do see one problem. Since you are saving the data to a separate file (chests.rxdata), if you have multiple save files the data will get overwritten.
It would make more sense to save the data to the current save file, so each game has it's own chest data.

A "Chest Empty" message would look better than an empty list. :scruff:

Be Well
 
i will fix that chest problem when i get home, thanks :) however it wouldn't show an empty window because of:
[rgss] 
if @data.size != 0
   refresh
else
   $scene = Scene_Map.new
end
[/rgss]

edit: ya ive never screwed with changing how the game saves and loads data, i thought i knew how to do it but i guess i dont, how would you recommend i do it?
 
kk i had a epiphany while playing mass effect 2 lol so i added the save you loaded to the chest name :D how ever not sure how to make it work when player chooses new game...and ideas brew?

p.s. if you are wondering why i didn't add it to save data, because i failed at adding it, and even then it would probably present issues with custom save scripts. so i thought i would just make the saves Chest_Save1.rxdata and so forth. im clueless on how to handle unsaved games though...

edit: my thoughts, tell me if im right...does it matter what i call it? as soon as they save i dont have to worry. and if they start a new game without saving it creates a new file anyways(well re-adds objects when you encounter them)after testing this i had no problems, but i still wanna know what you think
 
Do you guys think it would be easier if this whole script idea was, instead of being a Scene, it could just be a script that allows you to create separate windows that specify each item prompted by an event command?

For example you could say to create a window with ([x,x,x],[y,y,y],[z,z,z]) instead of having it be an actual scene that can be reused.
 

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