[XP] Item menu with pictures

Started by asukicco, December 16, 2010, 10:22:12 am

Previous topic - Next topic

asukicco

December 16, 2010, 10:22:12 am Last Edit: December 16, 2010, 07:38:04 pm by asukicco
Hi forum members,
I have a question for ya. Is it possible to have a picture showed in the item menu only for the current highlighted item?
I've resized the item list to one column to get room for this feature, I succesfully managed to make the class add a picture when an item with a certain description (I tried the same thing with item.name but something gone wrong). The problem is:
the item picture do not dispose after the higlighted item has changed, and the picture keeps being created over and over (I didn't experienced any lag because of this but it is surely not right). I tried making a class similiar to Window_Help class, but for some reason it doesn't recognize any method I put in that class (like draw_pix for example).

For now I have: [Window_Item]
#==============================================================================
# ** Window_Item
#------------------------------------------------------------------------------
#  This window displays items in possession on the item and battle screens.
#==============================================================================

class Window_Item < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(0, 64, 200, 300)
    @background = Spriteset_Map.new
    self.back_opacity = 160
    @column_max = 1
    refresh
    self.index = 0
    # 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 1...$data_items.size
      if $game_party.item_number(i) > 0
        @data.push($data_items[i])
      end
    end
    # Also add weapons and items if outside of battle
    unless $game_temp.in_battle
      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
    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
=begin
  def set_pix(pix)
    # If at least one part of text and alignment differ from last time
    if pix != @pix
      # Redraw text
      self.contents.clear
      self.contents.draw_pix2(200, 100, pix)
      @pix = pix
    end
    self.visible = true
  end
  def draw_pix2(pix_name, x, y)
    pix = pix_name
    pw = pix.width
    ph = pix.height
    src_rect = Rect.new(0, 0, pw, ph)
    self.contents.blt(x - pw / 23, y - ph, pix, src_rect)
  end
=end
  #--------------------------------------------------------------------------
  # * Draw Item
  #     index : item number
  #--------------------------------------------------------------------------
  def draw_item(index)
    item = @data[index]
    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
    if item.is_a?(RPG::Item) and
       $game_party.item_can_use?(item.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    #x = 4 + index % 2 * (288 + 32)
    x = 4 + index % 1 * (288 + 32)
    #y = index / 2 * 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)
    #self.draw_pix(200, 200, item.name.to_s)
    if number > 1
      #self.contents.draw_text(x + 240, y, 16, 32, ":", 1)
      self.contents.draw_text(x + 130, y, 16, 32, "x", 1)
      #self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2)
      self.contents.draw_text(x + 134, y, 24, 32, number.to_s, 2)
    end
    #bitmap = RPG::Cache.icon(item.name + "_desc")
    #self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
    #self.contents.draw_pix(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
  def update_itempix
    @itempix_window.drawpix(RPG::Cache.icon(item.name + "_desc"),10,10)
  #  @item_window.set_pix("Blood diamond_desc.png")
  end
end


[Window_Itempix]
#==============================================================================
# ** Window_Help
#------------------------------------------------------------------------------
#  This window shows skill and item explanations along with actor status.
#==============================================================================

class Window_Itempix < Window_Base
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(300, 100, 200, 200)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
  #--------------------------------------------------------------------------
  # * Set Text
  #  text  : text string displayed in window
  #  align : alignment (0..flush left, 1..center, 2..flush right)
  #--------------------------------------------------------------------------
  def drawpix(pix, x,y)
    # If at least one part of text and alignment differ from last time
    if pix != @pix
      # Redraw text
      self.contents.clear
      self.contents.font.color = normal_color
      self.contents.draw_pix(pix,x,y)
      @pix = pix
      @actor = nil
    end
    self.visible = true
  end
   def draw_pix(pix_name, x, y)
    pix = RPG::Cache.picture(pix_name)
    pw = pix.width
    ph = pix.height
    src_rect = Rect.new(0, 0, pw, ph)
    self.contents.blt(x - pw / 23, y - ph, pix, src_rect)
  end
  #--------------------------------------------------------------------------
  # * Set Actor
  #     actor : status displaying actor
  #--------------------------------------------------------------------------
  def set_actor(actor)
    if actor != @actor
      self.contents.clear
      draw_actor_name(actor, 4, 0)
      draw_actor_state(actor, 140, 0)
      draw_actor_hp(actor, 284, 0)
      draw_actor_sp(actor, 460, 0)
      @actor = actor
      @text = nil
      self.visible = true
    end
  end
end 


[Scene_Item]
#==============================================================================
# ** Scene_Item
#------------------------------------------------------------------------------
#  This class performs item screen processing.
#==============================================================================

class Scene_Item
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    # Make help window, item window, item pix window
    @help_window = Window_Help.new
    @item_window = Window_Item.new
    @itempix_window = Window_Itempix.new
    # Associate help window and item pix window
    @item_window.help_window = @help_window
#    @item_window.itempix_window = @itempix_window
    # Make target window (set to invisible / inactive)
    @target_window = Window_Target.new
    @target_window.visible = false
    @target_window.active = false
    # 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
    @help_window.dispose
    @item_window.dispose
    @target_window.dispose
    @itempix_window.dispose
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Update windows
    @help_window.update
    @item_window.update
    @target_window.update
    @itempix_window.update
    # If item window is active: call update_item
    if @item_window.active
      update_item
      return
    end
    # If target window is active: call update_target
    if @target_window.active
      update_target
      return
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update (when item window is active)
  #--------------------------------------------------------------------------
  def update_item
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to menu screen
      $scene = Scene_Menu.new(0)
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Get currently selected data on the item window
      @item = @item_window.item
      # If not a use item
      unless @item.is_a?(RPG::Item)
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # If it can't be used
      unless $game_party.item_can_use?(@item.id)
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # Play decision SE
      $game_system.se_play($data_system.decision_se)
      # If effect scope is an ally
      if @item.scope >= 3
        # Activate target window
        @item_window.active = false
        @target_window.x = (@item_window.index + 1) % 2 * 304
        @target_window.visible = true
        @target_window.active = true
        # Set cursor position to effect scope (single / all)
        if @item.scope == 4 || @item.scope == 6
          @target_window.index = -1
        else
          @target_window.index = 0
        end
      # If effect scope is other than an ally
      else
        # If command event ID is valid
        if @item.common_event_id > 0
          # Command event call reservation
          $game_temp.common_event_id = @item.common_event_id
          # Play item use SE
          $game_system.se_play(@item.menu_se)
          # If consumable
          if @item.consumable
            # Decrease used items by 1
            $game_party.lose_item(@item.id, 1)
            # Draw item window item
            @item_window.draw_item(@item_window.index)
          end
          # Switch to map screen
          $scene = Scene_Map.new
          return
        end
      end
      return
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update (when target window is active)
  #--------------------------------------------------------------------------
  def update_target
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # If unable to use because items ran out
      unless $game_party.item_can_use?(@item.id)
        # Remake item window contents
        @item_window.refresh
      end
      # Erase target window
      @item_window.active = true
      @target_window.visible = false
      @target_window.active = false
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # If items are used up
      if $game_party.item_number(@item.id) == 0
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # If target is all
      if @target_window.index == -1
        # Apply item effects to entire party
        used = false
        for i in $game_party.actors
          used |= i.item_effect(@item)
        end
      end
      # If single target
      if @target_window.index >= 0
        # Apply item use effects to target actor
        target = $game_party.actors[@target_window.index]
        used = target.item_effect(@item)
      end
      # If an item was used
      if used
        # Play item use SE
        $game_system.se_play(@item.menu_se)
        # If consumable
        if @item.consumable
          # Decrease used items by 1
          $game_party.lose_item(@item.id, 1)
          # Redraw item window item
          @item_window.draw_item(@item_window.index)
        end
        # Remake target window contents
        @target_window.refresh
        # If all party members are dead
        if $game_party.all_dead?
          # Switch to game over screen
          $scene = Scene_Gameover.new
          return
        end
        # If common event ID is valid
        if @item.common_event_id > 0
          # Common event call reservation
          $game_temp.common_event_id = @item.common_event_id
          # Switch to map screen
          $scene = Scene_Map.new
          return
        end
      end
      # If item wasn't used
      unless used
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
      end
      return
    end
  end
end



With this current setup I want to draw the picture in the blue window to the right, but nothing happens.
Any help?

If you need anything else just ask :)
Note: icons and tiles are made by me.

asukicco

December 17, 2010, 07:41:21 am #1 Last Edit: December 17, 2010, 12:19:02 pm by asukicco
self.bump

I got rid of itempix code and tried a different way in the meantime.
I put a draw_pix in the update help section of Window_Item:

#--------------------------------------------------------------------------
 # * Help Text Update
 #--------------------------------------------------------------------------
 def update_help
   @help_window.set_text(self.item == nil ? "" : self.item.description)
   self.draw_pix(item.name + "_desc", 0, 0)
 end


The draw_pix is in a script above main:

class Window_Base < Window

 def draw_actor_face(actor, x, y)
   face = RPG::Cache.character("Faces/" + actor.character_name, actor.character_hue)
   fw = face.width
   fh = face.height
   src_rect = Rect.new(0, 0, fw, fh)
   self.contents.blt(x - fw / 23, y - fh, face, src_rect)
   end
 
 def draw_pix(pix_name, x, y)
   pix = RPG::Cache.picture(pix_name)
   pw = pix.width
   ph = pix.height
   src_rect = Rect.new(0, 0, pw, ph)
   self.contents.blt(x - pw / 23, y - ph, pix, src_rect)
 end
end


The problem is: draw_pix works since I used it to customize Blizz-ABS HUD, but it seems to show nothing in Window_Item. But if the imagefile (item.name + "_desc") is missing, the game says so. It is working or not? I don't get it.

EDIT: Important! Things now works, thanks to game_guy suggestion I edited Scene_Item instead of Window_Item!

This is the Scene_Item now:
#==============================================================================
# ** Scene_Item
#------------------------------------------------------------------------------
#  This class performs item screen processing.
#==============================================================================

class Scene_Item
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    # Make help window, item window, item pix window
    @help_window = Window_Help.new
    @item_window = Window_Item.new
    @itempix_window = Window_Itempix.new
    # Associate help window and item pix window
    @item_window.help_window = @help_window
    @item_window.itempix_window = @itempix_window
    # Make target window (set to invisible / inactive)
    @target_window = Window_Target.new
    @target_window.visible = false
    @target_window.active = false
    # 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
    @help_window.dispose
    @item_window.dispose
    @target_window.dispose
    @itempix_window.dispose
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Update windows
    @help_window.update
    @item_window.update
    @target_window.update
    @itempix_window.update
    @itempix_window.drawpix(RPG::Cache.icon(@item_window.item.name + "_desc"),100,100)

    # If item window is active: call update_item
    if @item_window.active
      update_item
      return
    end
    # If target window is active: call update_target
    if @target_window.active
      update_target
      return
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update (when item window is active)
  #--------------------------------------------------------------------------
  def update_item
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to menu screen
      $scene = Scene_Menu.new(0)
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Get currently selected data on the item window
      @item = @item_window.item
      # If not a use item
      unless @item.is_a?(RPG::Item)
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # If it can't be used
      unless $game_party.item_can_use?(@item.id)
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # Play decision SE
      $game_system.se_play($data_system.decision_se)
      # If effect scope is an ally
      if @item.scope >= 3
        # Activate target window
        @item_window.active = false
        @target_window.x = (@item_window.index + 1) % 2 * 304
        @target_window.visible = true
        @target_window.active = true
        # Set cursor position to effect scope (single / all)
        if @item.scope == 4 || @item.scope == 6
          @target_window.index = -1
        else
          @target_window.index = 0
        end
      # If effect scope is other than an ally
      else
        # If command event ID is valid
        if @item.common_event_id > 0
          # Command event call reservation
          $game_temp.common_event_id = @item.common_event_id
          # Play item use SE
          $game_system.se_play(@item.menu_se)
          # If consumable
          if @item.consumable
            # Decrease used items by 1
            $game_party.lose_item(@item.id, 1)
            # Draw item window item
            @item_window.draw_item(@item_window.index)
          end
          # Switch to map screen
          $scene = Scene_Map.new
          return
        end
      end
      return
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update (when target window is active)
  #--------------------------------------------------------------------------
  def update_target
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # If unable to use because items ran out
      unless $game_party.item_can_use?(@item.id)
        # Remake item window contents
        @item_window.refresh
      end
      # Erase target window
      @item_window.active = true
      @target_window.visible = false
      @target_window.active = false
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # If items are used up
      if $game_party.item_number(@item.id) == 0
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # If target is all
      if @target_window.index == -1
        # Apply item effects to entire party
        used = false
        for i in $game_party.actors
          used |= i.item_effect(@item)
        end
      end
      # If single target
      if @target_window.index >= 0
        # Apply item use effects to target actor
        target = $game_party.actors[@target_window.index]
        used = target.item_effect(@item)
      end
      # If an item was used
      if used
        # Play item use SE
        $game_system.se_play(@item.menu_se)
        # If consumable
        if @item.consumable
          # Decrease used items by 1
          $game_party.lose_item(@item.id, 1)
          # Redraw item window item
          @item_window.draw_item(@item_window.index)
        end
        # Remake target window contents
        @target_window.refresh
        # If all party members are dead
        if $game_party.all_dead?
          # Switch to game over screen
          $scene = Scene_Gameover.new
          return
        end
        # If common event ID is valid
        if @item.common_event_id > 0
          # Common event call reservation
          $game_temp.common_event_id = @item.common_event_id
          # Switch to map screen
          $scene = Scene_Map.new
          return
        end
      end
      # If item wasn't used
      unless used
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
      end
      return
    end
  end
end


There's still probably a lot of lines to be cleaned, but it's ok right now.