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.

Container Script

Status
Not open for further replies.
I'd like a script that would allow you to withdraw/deposit items/weapons/armor into/out of a container. I want it to use a windowskin that I could choose, and it should look like this:
http://i162.photobucket.com/albums/t241 ... mple-1.png[/IMG]
It would look like that if a Bronze Knife was in it, for example.
I'd want it so I could set items to already be in it, and so its inventory would be unique to that specific container. If 2 items were in it, one being the Bronze Knife, it would have the other item/weapon/armor's icon on the right of the Bronze Knife's icon. Then when that row was filled, it would go to the next one. I'd also like it to be compatible with Mr.Mo's ABS.

Anybody able to do this?
Thanks.
 
This is on my 'need' list for my next game too. Although it could be a while.

Possible additions / enhancements:
- set size of container (# of items, size/weight*)
- image for background (open chest, bag, etc.) instead of windowskin.
- also limit the contents of the Items menu, so containers would be necessary to add more items.

just thoughts

Itachi, were you looking to replace the Items menu? Or Expand it? (the container would be an item, and when opened showed it's contents.)

*of course, items would have to have size or weight properties added. I saw one system in a game that used items of different sizes (they took up more than one square in the grid). I don't think it was an RMXP game though.

either way, it's a cool idea.

Be Well
 

poccil

Sponsor

I've finished creating code that meets your request.

The script consists of two parts, ItemStorage and ItemStorageDisplay. ItemStorage manages the
items in storage, and ItemStorageDisplay displays them. Here are definitions of each class:

ItemStorage
  • ItemStorage.new(maxsize) - Creates a new ItemStorage with the specified _maxsize_.
  • full? - Returns true if storage is full.
  • deposit(itemtype,id) - Deposits an item of the specified _itemtype_ and _id_ to storage. Returns true if the item was stored. The _itemtype_ can be ItemStorage::ITEM, ItemStorage::WEAPON, or ItemStorage::ARMOR.
  • withdraw(position) - Withdraws an item of the specified _position_ from storage.
  • iteminfo(pos) - Gets info about the item stored in the specified position, or nil if no item is stored there.
    The return value is either RPG::Item, RPG::Weapon, or RPG::Armor.
  • itemtype(pos) - Gets the item type of the item stored in the specified position, or 0 if no item is stored there.
  • itemid(pos) - Gets the ID of the item stored in the specified position, or 0 if no item is stored there.
  • itemname(pos) - Gets the name of the item stored in the specified position, or "" if no item is stored there.
  • itemicon(pos) - Gets the icon name of the item stored in the specified position, or "" if no item is stored there.
ItemStorageDisplay
  • ItemStorageDisplay.new(storage,[viewport]) - Creates a new ItemStorageDisplay using the specified ItemStorage object and viewport.
  • x, x=(value) - X coordinate.
  • y, y=(value) - Y coordinate.
  • z, z=(value) - Z coordinate.
  • width, height - Storage display's width and height in pixels.
  • opacity, opacity=(value) - Opacity.
  • visible, visible=(value) - Visibility.
  • storage=(value) - Changes item storage.
  • windowskin=(value) - Changes windowskin. The windowskin image has a 12-pixel-wide border around it and a tiled center of 24 pixels.
    The image measures 48x48 pixels.
  • setSize(width,height) - Sets the number of rows and columns of the display.
  • dispose - Disposes the storage display.

The script code follows...

Code:
class WindowParts
 attr_accessor :width, :height, :x, :y
 attr_accessor :borderx, :bordery
 def initialize(width,height)
  # Corners
  @width=width  # Width of skin image
  @height=height # Height of skin image
  @borderx=12
  @bordery=12
  @x=0
  @y=0
  @corners=[
   Rect.new(0,0,0,0),
   Rect.new(0,0,0,0),
   Rect.new(0,0,0,0),
   Rect.new(0,0,0,0)
  ]
  # Sides
  @sides=[
   Rect.new(0,0,0,0),
   Rect.new(0,0,0,0),
   Rect.new(0,0,0,0),
   Rect.new(0,0,0,0)
  ]
  # Background rectangle
  @back=Rect.new(0,0,0,0)
  refresh
 end
 def getWindowPieces
  refresh
  ret=[]
  for corner in @corners
   ret.push(corner.clone)
  end
  for side in @sides
   ret.push(side.clone)
  end
  ret.push(@back.clone)
  return ret
 end
 def refresh
  # Calculate corner rectangles
  @corners[0].set(0,0,@borderx,@bordery) # NW
  @corners[1].set(@width-@borderx,0,@borderx,@bordery) # NE
  @corners[2].set(0,@height-@bordery,@borderx,@bordery) # SW
  @corners[3].set(@width-@borderx,@height-@bordery,@borderx,@bordery) # SE
  # Calculate side dimensions of window
  sidewidth=[0,@width-@borderx*2].max
  sideheight=[0,@height-@bordery*2].max
  # Calculate side rectangles
  @sides[0].set(@borderx,0,sidewidth,@bordery) # N
  @sides[1].set(0,@bordery,@borderx,sideheight) # W
  @sides[2].set(@width-@borderx,@bordery,@borderx,sideheight) # E
  @sides[3].set(@borderx,@height-@bordery,sidewidth,@bordery) # S
  # Calculate background
  @back.set(@borderx,@bordery,sidewidth,sideheight)
  for corner in @corners
   corner.x+=@x
   corner.y+=@y
  end
  for side in @sides
   side.x+=@x
   side.y+=@y
  end
  @back.x+=@x
  @back.y+=@y
 end
end

class TilingHelper
 # Tiles the bitmap in srcbitmap to dstbitmap. 
 def self.tileBitmap(dstbitmap,dstrect,srcbitmap,srcrect)
  dstbitmap.clear
  return if !srcbitmap || srcrect.width<=0 || srcrect.height<=0
  left=dstrect.x
  top=dstrect.y
  y=0;while y<dstrect.height
   x=0;while x<dstrect.width
    dstbitmap.blt(x+left,y+top,srcbitmap,srcrect)
    x+=srcrect.width
   end
   y+=srcrect.height
  end
 end
 # Ensures that the bitmap is big enough.  dwidth and dheight
 # are the desired width and height
 def self.ensureBitmap(bitmap,dwidth,dheight)
  if !bitmap||bitmap.disposed?||bitmap.width<dwidth||bitmap.height<dheight
   bitmap.dispose if bitmap
   bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
  end
  return bitmap
 end
 # Tiles the given sprite with the given skin and rectangle
 # skinSrcRect is the source rect of the skin's image
 # spriteDstRect is the desired X and Y of the sprite as well as 
 # its desired size
 def self.tileSprite(sprite, skin, skinSrcRect, spriteDstRect)
  return if !sprite || sprite.disposed?
  # position sprite
  sprite.x=spriteDstRect.x
  sprite.y=spriteDstRect.y
  if !skin
   sprite.bitmap.dispose if sprite.bitmap
   sprite.bitmap=nil
  else
   # allocate bitmap if necessary
   sprite.bitmap=self.ensureBitmap(sprite.bitmap,
      spriteDstRect.width,spriteDstRect.height)
   sprite.src_rect.set(0,0,spriteDstRect.width, spriteDstRect.height)
   self.tileBitmap(sprite.bitmap,sprite.src_rect,skin,skinSrcRect)
  end
 end
end
class GenericSkinDisplay
 attr_reader :x,:y,:width,:height,:z,:opacity,:visible
 # Initializes the display with the specified viewport.
 def initialize(viewport=nil)
  @windowsprites=[]
  for i in 0...9
   @windowsprites[i]=Sprite.new(viewport)
  end
  @windowskin=nil
  @skinparts=WindowParts.new(0,0)
  @windowparts=WindowParts.new(0,0)
  @viewport=viewport
  @updateDisplay=true
  @x=0
  @y=0
  @z=0
  @width=0
  @height=0
  @opacity=255
  @visible=true
  privRefresh
 end
 def dispose
  for sprite in @windowsprites
   sprite.bitmap.dispose if sprite.bitmap
   sprite.dispose
  end
  @windowsprites.clear
 end
 def windowskin=(value)
  @windowskin=value
  if value
    @skinparts.width=value.width
    @skinparts.height=value.height
  end
  @updateDisplay=true
  privRefresh
 end
 def width=(value)
  @width=value
  @updateDisplay=true
  @windowparts.width=value
  privRefresh
 end
 def height=(value)
  @height=value
  @updateDisplay=true
  @windowparts.height=value
  privRefresh
 end
 def x=(value)
  @x=value
  @windowparts.x=value
  privRefresh
 end
 def y=(value)
  @y=value
  @windowparts.y=value
  privRefresh
 end
 def z=(value)
  @z=value
  privRefresh
 end
 def opacity=(value)
  @opacity=value
  privRefresh
 end
 def visible=(value)
  @visible=value
  privRefresh
 end
 private
 def privRefresh
  windowrects=@windowparts.getWindowPieces
  if @updateDisplay
   skinrects=@skinparts.getWindowPieces
   for i in 0...9
    TilingHelper.tileSprite(@windowsprites[i],
      @windowskin,skinrects[i],windowrects[i])
    @windowsprites[i].z=@z
    @windowsprites[i].opacity=@opacity
    @windowsprites[i].visible=@visible
   end
   @updateDisplay=false
  else
   for i in 0...9
    @windowsprites[i].x=windowrects[i].x
    @windowsprites[i].y=windowrects[i].y
    @windowsprites[i].z=z
    @windowsprites[i].opacity=@opacity
    @windowsprites[i].visible=@visible
   end   
  end
 end
end

class ItemStorage
 ITEM=1
 WEAPON=2
 ARMOR=3
 attr_reader :maxsize
 # Initializes item storage
 def initialize(maxsize)
  @items=[]
  @maxsize=maxsize
 end
 # Returns true if storage is full.
 def full?
  for i in 0...@maxsize
   return false if !@items[i]
  end
  return true
 end
 # Deposits an item to storage.  Returns
 # true if the item was stored.
 def deposit(itemtype,id)
  for i in 0...@maxsize
   if !@items[i]
    @items[i]=[itemtype,id]
    return true
   end
  end
  return false
 end
 # Withdraws an item from storage.
 def withdraw(pos)
  @items[pos]=nil
  @items.compact!
 end
 # Gets the item type of the item in storage,
 # or 0 if no item is stored there.
 def itemtype(pos)
  item=@items[pos]
  return item ? item[0] : -1
 end
 # Gets the ID of the item in storage,
 # or 0 if no item is stored there.
 def itemid(pos)
  item=@items[pos]
  return item ? item[1] : -1
 end
 # Gets info about the item stored
 # in the specified position, or nil if no item
 # is stored there.
 def iteminfo(pos)
  item=@items[pos]
  if item
   case item[0]
   when ITEM
    return $data_items[item[1]]
   when WEAPON
    return $data_weapons[item[1]]
   when ARMOR
    return $data_armors[item[1]]
   else
    return nil
   end
  end
  return nil
 end
 # Gets the name/icon name of the item stored in the specified
 # position, or the empty string if no item is stored there
 def itemname(pos)
  item=iteminfo(pos)
  return item ? item.name : ""
 end
 def itemicon(pos)
  item=iteminfo(pos)
  return item ? item.icon_name : ""
 end
end
class ItemStorageDisplay
  attr_reader :storage
  def initialize(storage,viewport=nil)
    @gsd=GenericSkinDisplay.new(viewport)
    @sprites=[]
    @spriteicons=[]
    @storage=storage
    @storagewidth=0
    @storageheight=0
    @viewport=viewport
    refresh
  end
  def width;@gsd.width;end
  def height;@gsd.height;end
  def x;@gsd.x;end
  def x=(value);@gsd.x=value;refresh;end
  def y;@gsd.y;end
  def y=(value);@gsd.y=value;refresh;end
  def z;@gsd.z;end
  def z=(value);@gsd.z=value;refresh;end
  def opacity;@gsd.opacity;end
  def opacity=(value);@gsd.opacity=value;refresh;end
  def visible;@gsd.visible;end
  def visible=(value);@gsd.visible=value;refresh;end
  def dispose
    @gsd.dispose
    for sprite in @sprites
      sprite.dispose
    end
  end
  def storage=(value)
    @storage=value
    refresh
  end
  def windowskin=(value)
    @gsd.windowskin=value
  end
  def setSize(width,height)
    @storagewidth=width
    @storageheight=height
    @gsd.width=24+width*24
    @gsd.height=24+height*24
  end
  def refresh
    for i in 0...@storage.maxsize
      iconname=@storage.itemicon(i)
      if iconname==""
        @sprites[i].visible=false if @sprites[i]
      else
        if !@sprites[i]
          @sprites[i]=Sprite.new(@viewport)
        end
        if iconname!=@spriteicons[i]
          @sprites[i].bitmap=RPG::Cache.icon(iconname)
          @spriteicons[i]=iconname
        end
      end
      storagesize=@storagewidth*@storageheight
      if @sprites[i] 
        if i<storagesize
          @sprites[i].x=@gsd.x+12+((i%@storagewidth)*24)
          @sprites[i].y=@gsd.y+12+((i/@storagewidth)*24)
          @sprites[i].z=@gsd.z
          @sprites[i].opacity=@gsd.opacity
          @sprites[i].visible=@gsd.visible
        else
          @sprites[i].visible=false
        end
      end
    end    
  end
  def update
    refresh
  end
end
 

poccil

Sponsor

The above was actually designed for advanced users of scripts. However, I am working on a simpler way to use containers from scripts. I will edit this post when I am finished.

EDIT:


I have created some functions for using containers within
Script event commands. They are defined below:
  • showContainer(num,[x,[y]]) - Shows the container numbered _num_ and
    optionally displays it at position _x_ and _y_. Example: showContainer(0,40,30)
    creates a container numbered 0 and displays it at the coordinates (40,30).
  • addToContainer(num, type, id) - Adds an item to the container numbered _num_ and
    which has the specified _type_ and _id_. _type_ can be ItemStorage::ITEM,
    ItemStorage::WEAPON, or ItemStorage::ARMOR, or 1, 2, or 3, respectively.
    Example: addToContainer(0,ItemStorage::WEAPON,1) stores a weapon with
    the ID 1.
  • containerItemName(num,pos,var) - Gets the name of the item located at position
    _pos_ within the container _num_ and stores it in the variable numbered _variable_.
  • removeFromContainer(num,pos) - Removes the item located at position
    _pos_ from the container _num_.
  • hideContainer(num) - Closes the container _num_, but the storage (from
    getStorage) remains.
  • getContainer(num) - Gets the ItemStorageDisplay object numbered _num_.
  • getStorage(num) - Gets the ItemStorage object numbered _num_.

I have also edited the script code above. Please use that updated version. Also please note the configuration section at the top of the script code below.

The script code follows...

Code:
###############

class ItemStorageDisplay
  # Default windowskin.  48x48 with a 24x24 center.
  # Must be in Graphics/Windowskins.
  DEFAULTSKIN="window.png"
  # Default maximum size of storage
  DEFAULTMAXSIZE=64
  # Default rows and columns of containers
  DEFAULTWIDTH=8
  DEFAULTHEIGHT=8
  # Default Z order for containers
  DEFAULTZ=100
end

###############

class Game_System
  attr_accessor :containers
end

class Game_Temp
  attr_accessor :containerwindows
end


# Gets the storage display (ItemStorageDisplay)
def getContainer(containerID)
 return nil if !$game_temp.containerwindows
 c=$game_temp.containerwindows[containerID]
 return c
end

# Gets the storage (ItemStorage)
def getStorage(containerID)
 return nil if !$game_system.containers
 return $game_system.containers[containerID]
end

# Shows the container.
def showContainer(containerID, x=0, y=0)
 storage=getStorage(containerID)
 if !storage
  storage=ItemStorage.new(
    ItemStorageDisplay::DEFAULTMAXSIZE)
  if !$game_system.containers
   $game_system.containers=[]
  end
  $game_system.containers[containerID]=storage
 end
 container=ItemStorageDisplay.new(storage)
 container.z=ItemStorageDisplay::DEFAULTZ
 container.windowskin=RPG::Cache.windowskin(
    ItemStorageDisplay::DEFAULTSKIN)
 container.setSize(
    ItemStorageDisplay::DEFAULTWIDTH,
    ItemStorageDisplay::DEFAULTHEIGHT
 )
 container.x=0
 container.y=0
 if !$game_temp.containerwindows
  $game_temp.containerwindows=[]
 end
 $game_temp.containerwindows[containerID]=container
 return container
end

def addToContainer(containerID, itemtype, itemid)
 storage=getStorage(containerID)
 if storage
  storage.deposit(itemtype,itemid)
 end
 c=getContainer(containerID)
 if c
  c.refresh
 end
end

def containerItemName(containerID, pos, variable)
 storage=getStorage(containerID)
 if storage
  $game_variables[variable]=storage.itemname(pos)
 else
  $game_variables[variable]=""
 end
end

def removeFromContainer(containerID, pos)
 storage=getStorage(containerID)
 if storage
  storage.withdraw(pos)
 end
 c=getContainer(containerID)
 if c
  c.refresh
 end
end

# Hides the container
def hideContainer(containerID)
 c=getContainer(containerID)
 if c
  c.dispose
  $game_temp.containerwindows[containerID]=nil
 end
end
 
Thanks. ^_^
The item's icon isn't appearing to show, though.
Edit: Never mind, it works now.
Just had to use the event again.

Edit #2: Works perfectly, and it works with Mr.Mo's ABS. :D
Thanks a million.

Resolved.
 

poccil

Sponsor

As I mentioned, I have updated the first part of the script to fix a bug with it. Here is the relevant portion of it (near the bottom of the first part):

Code:
        if i<storagesize
          @sprites[i].x=@gsd.x+12+((i%@storagewidth)*24)
          @sprites[i].y=@gsd.y+12+((i/@storagewidth)*24)
[b]          @sprites[i].z=@gsd.z[/b]
          @sprites[i].opacity=@gsd.opacity
          @sprites[i].visible=@gsd.visible
        else
          @sprites[i].visible=false


EDIT: Oh, I'm glad to see it works for you then. That makes me glad.
 

poccil

Sponsor

The function addToContainer adds (deposits) an item to a container. Here is an example:

addToContainer(0,ItemStorage::WEAPON,1)

This example stores a weapon with the ID numbered 1 to the container numbered 0.

The function removeFromContainer takes a position number within the container as its parameters. It removes (withdraws) an item from storage. Here is an example:

removeFromContainer(0,1)

removes the item located in the position 1 (right next to the top left corner) in the container numbered 0.

The following are expanded functions that manage items between a container and the player's party (they otherwise work the same as addToContainer and removeFromContainer):

Code:
def addToContainerAndLose(containerID, itemtype, itemid)
 storage=getStorage(containerID)
 if storage
  # Get item ID
  if storage.deposit(itemtype,itemid)
   case itemtype
    when ItemStorage::ITEM
     $game_party.lose_item(itemid,1)
    when ItemStorage::WEAPON
     $game_party.lose_weapon(itemid,1)
    when ItemStorage::ARMOR
     $game_party.lose_armor(itemid,1)
   end
  end  
 end
 c=getContainer(containerID)
 if c
  c.refresh
 end
end

def removeFromContainerAndGain(containerID, pos)
 storage=getStorage(containerID)
 if storage
  # Get item ID
  itemID=storage.itemid(pos)
  case storage.itemtype(pos)
   when ItemStorage::ITEM
    $game_party.gain_item(itemID,1)
   when ItemStorage::WEAPON
    $game_party.gain_weapon(itemID,1)
   when ItemStorage::ARMOR
    $game_party.gain_armor(itemID,1)
  end
  storage.withdraw(pos)
 end
 c=getContainer(containerID)
 if c
  c.refresh
 end
end
 
Status
Not open for further replies.

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