Results 1 to 39 of 39
  1. #1
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default Inventory Tutorial

    Before i go on and post a tutorial on inventory. (custom inventory) Not using the ut inventory.

    How many people actually require this?

    This would be an RPG style inventory.

    Tutorial.

    First we start with the inventory manager which will extend Actor.\

    This class will hold all o four stored items as well as make checks to see if you are full of that certain item.

    U_InventoryManager.uc

    Code:
    //=============================================================================
    // U_InventoryManager
    //
    // Manages all of the inventory in the game. performs checks it its full and 
    // handles removing and adding inventory
    
    //=============================================================================
    
    class U_InventoryManager extends Actor;
    
    //Array of items in the inventory
    var array<U_Items> UItems;
    
    // Used to spawn and add item into inventory
    var U_Items AddItem;
    
    var int Gold;
    var int MaxGold;
    
    var  UHUD HUD;
    
    simulated event PostBeginPlay()
    {
    
    
            super.PostBeginPlay();
    	`Log("Custom Inventory up");
            //find the playercontroller and reference it
    
            StartingInventory();
    }
    
    function AddGold(int GoldAmount)
    {
        if(Gold + GoldAmount >= MaxGold)
        {
            Gold = MaxGold;
        }
        else
        {
            Gold += GoldAmount;
        }
    }
    
    //@params ItemToCheck item specified in the U_WorldItemPickup class
    //@params AmountWantingToAdd the int amount that is specified in the U_WorldItemPickUp class
    //
    //returns false if there is space in the inventory returns true if there is not enough space.
    
    function bool CheckInventorySize(class<U_Items> ItemToCheck, int AmountWantingToAdd)
    {
      local int ItemAmountInInventory;
      local int i;
    
      for (i=0;i<UItems.Length;i++)
      {
                        //When the iterator reaches a class that macthes the one that you want add it to itemamountininventory
         if (UItems[i].Class == ItemToCheck)
          {
            ItemAmountInInventory ++;
            `log(""@ItemToCheck$" Has"@ItemAmountInInventory$"Items");
          }
    
       }
       
          if((ItemAmountInInventory + AmountWantingToAdd) >= 50)
          {
             ItemAmountInInventory = 0;
             `log("no more Space for items");
             return true;
          }
          else
          {
             ItemAmountInInventory = 0;
             `log("has Space for items");
             return false;
          }
    
    
    }
    
      //default stuff in the beggining of the game (you always have a herb on game start incase the player saves the game with low low health.)
      function StartingInventory()
    {
             AddInventory(class'U_HerbItem', 1);
    }
    
    
    //Add items to the current inventory
    function AddInventory(class<U_Items> ItemType, int Amount )
    {
         local int			i;
    
         for ( i=0; i<Amount; i++ )
          {
             //Spawn the abstract item when the physical object is picked up and store it
             AddItem = Spawn(ItemType);
             UItems.AddItem(AddItem);
          }
          `log("There are" @ UItems.length @ "Items");
    }
    
    //Remove items from the current inventory either when used or dropped.
    function RemoveInventory(class<U_Items> ItemToRemove, int Amount)
    {
         local int			i;
         local U_Items		Item;
    
    
            	for (i=0;i<UItems.Length;i++)
                    {
                        //When the iterator reaches a class that macthes the one that you want to use or remove. 
                        // Remove it [i] and then use it.
                        if (UItems[i].Class == ItemToRemove)
                         {
    
                               UItems.Remove(i,Amount);
                               break;
                         }
                    }
    
          `log("Now there are only" @ UItems.length @ "Items!");
    
         //Display the items left just for debugging.
          foreach UItems(Item, i)
    	{
    		`log("Index=" $ i @ "Value=" $ Item);
    	}
    }
    
    function NotifyHUDMessage(string Message, optional int Amount, optional string ItemName)
    {
      foreach AllActors(class'UHUD', HUD)
      {
       HUD.Message = Message;
       HUD.TAmount = Amount;
       HUD.ItemName = ItemName;
       HUD.bItemPickedUp = true;
      }
    }
    
    defaultproperties
    {
      Gold = 500
      MaxGold = 99999
    }
    Next we need to create the base abstract class that will be our inventory inside of the hud. You can extend this and create as many of these classes as you want.

    Inside these classes can be functions that will heal the player or do something else that fits your needs. Right now they are empty classes.

    U_Items.uc

    Code:
    //=============================================================================
    // U_Items
    //
    // Parent Class of all Iventory items to be added in the InventoryManager
    //
    // This class in intereacted with in the Inventory manager as well as the MenuScene GUI
    // When the player selects the item in the GUI the HUD notifies the inventory manager and tells
    // the item in the array that is is bieng focused on. Making it read to be used and call remove inventory at any time
    //
    // Copyright 2011-2012 Jonathan Vazquez All Rights Reserved.
    //=============================================================================
    //class that holds the functions and uses of each item
    
    //These classes extending U_Items will be added once a physical pickup is picked up
    
    class U_Items extends Actor abstract;
    This is a test extension of UItems

    Code:
    class U_HerbItem  extends U_Items placeable;

    This is a quick HUD to display our messages

    UHUD.uc

    Code:
    class UHUD extends UDKHUD;
    
    //message pickup properties
    var string Message;
    var int TAmount;
    var string ItemName;
    var float Alpha;
    
    var bool bItemPickedUp;
    
    var Font PlayerFont;
    
    event PostRender()
    {
      HandlePickUpMessage();
    
      Super.PostRender();
    }
    
    //Shows the picked up item as well as handle fading
    function HandlePickUpMessage()
    {
       local float RenderTime;
       local float X,Y,UL,VL;
    
       Canvas.Font = PlayerFont;
      
       Canvas.TextSize(""@Message$" "@TAmount$" "@ItemName$"(s)",UL,VL);
    
    		X =  (SizeX / 2) - (UL/2);
    		Y =  (200) - (VL/2);
    
    		Canvas.SetPos( X, Y);
    
    
             // Set the cursor color
       Canvas.SetDrawColor(255, 255, 255, Alpha);
       
       Canvas.DrawText(""@Message$" "@TAmount$" "@ItemName$"(s)");
    
       if(bItemPickedUp == true)
       {
         if(RenderTime == 0)
            RenderTime = WorldInfo.TimeSeconds;
       }
    
        if(`TimeSince(RenderTime) > 1.0)
        {
    
            Alpha = Lerp(Alpha, 0 , 0.05);
            RenderTime -= 0.1;
        }
       else
       {
         RenderTime = 0;
         Alpha = 255;
         bItemPickedUp = false;
       }
    }
    In order to make use of the inventory manager you must add a few things to your pawn

    Code:
    var class<U_InventoryManager>		UInventory;
    var repnotify U_InventoryManager			UManager;
    
    simulated event PostBeginPlay()
    {
    	super.PostBeginPlay();
    	`Log("Custom Pawn up");
        
            //Set up custom inventory manager
            if (UInventory != None)
    	{
    		UManager = Spawn(UInventory, Self);
    		if ( UManager == None )
    			`log("Warning! Couldn't spawn InventoryManager" @ UInventory @ "for" @ Self @  GetHumanReadableName() );
    
    	}
    }
    
    
    defaulproperties
    {
       bCanPickUpInventory = true
       UInventory = U_InventoryManager
    }

    Now we need to create the actual pickup that adds the abstract classes into the inventory. These classes can play sounds on pick up display a message etc.

    You simply choose what item you want to add from a dropdown menu so it saves you from creating a million pickup classes.

    U_WorldItemPickup.uc

    Note : Make sure you replace UHeroPawn with your pawn. Or any other un - matching classes with yours.

    Code:
    class U_WorldItemPickup extends Actor placeable;
    
    var() editconst const CylinderComponent	CylinderComponent;
    var() const editconst DynamicLightEnvironmentComponent LightEnvironment;
    
    
    //the physical pickup that is seen in the world as a "Bag" which will contain any kind of inventory and a certain amount.
    
    var     U_InventoryManager	InvManager;
    
    var()	string	ItemName;
    
    var()   string	PickupMessage;			// Human readable description when picked up.
    
    var() SoundCue PickupSound;
    
    var() class<U_Items> ItemType;
    
    var() int ItemAmount_ADD;
    
    var UHeroPawn UHP;
    
    event Touch(Actor Other, PrimitiveComponent OtherComp, Vector HitLocation, Vector HitNormal)
    {
        super.Touch(Other, OtherComp, HitLocation, HitNormal);
    
        UHP = UHeroPawn(Other);
    
        if (UHP != none)
        {
           //If the inventory check returns false (has space) add the item.
           if(!(UHP.UManager.CheckInventorySize(ItemType, ItemAmount_ADD)))
           {
             //Add the picked up item
             GiveTo(UHP);
             PlaySound(PickUpSound);
             UHP.UManager. NotifyHUDMessage(PickUpMessage, ItemAmount_ADD, ItemName);
           }
        }
    }
    
    
    //Add to pawns inventory once picked up
    //If you still have space add it to the inventory
     function GiveTo( UHeroPawn Other )
    {
    	if ( Other != None && Other.UManager != None )
    	{
    		Other.UManager.AddInventory(ItemType, ItemAmount_ADD );
    		Destroy();
    	}
    
    }
    
    defaultproperties
    {
        Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment
            bEnabled=TRUE
        End Object
    
        LightEnvironment=MyLightEnvironment
        Components.Add(MyLightEnvironment)
    
    
        Begin Object class=StaticMeshComponent Name=BaseMesh
            StaticMesh=None //StaticMesh'Items.Items.ItemBag' Add your own staticmesh
            Scale = 3.5
            LightEnvironment=MyLightEnvironment
        End Object
        Components.Add(BaseMesh)
        
        Begin Object Class=CylinderComponent NAME=CollisionCylinder
    		CollideActors=true
    		CollisionRadius=+0040.000000
    		CollisionHeight=+0040.000000
    		bAlwaysRenderIfSelected=true
    	End Object
    	CollisionComponent=CollisionCylinder
    	CylinderComponent=CollisionCylinder
    	Components.Add(CollisionCylinder)
    
    	bHidden=false
    	bCollideActors=true
    }

    That should be it. It i missed anything let me know!
    Last edited by TheAgent; 09-10-2011 at 12:05 PM.

  2. #2
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    Ofcourse man, that would be absolutely awesome.
    I just used your Vaulting Script. Couldn't be happier xD

    When could you have it finished?

  3. #3
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    Probably later today i hope, i going to be a bit busy given that i just finished moving in to my dorm at college and what not. But either today or tomorrow : ].

  4. #4
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    Sounds awesome man, i'm looking forward to read it

  5. #5

    Default

    i would be interesed on it

  6. #6
    MSgt. Shooter Person
    Join Date
    Jan 2010
    Location
    Germany, Bavaria
    Posts
    168

    Default

    diablo II like inventory? with items of different sizes ???
    Synoptic-Entertainment <--> Fail-Production

    Sex is like Hacking . You get in, you get out, then you hope that you didn't leave something behind that can be traced back to you.

  7. #7
    Prisoner 849
    Join Date
    Nov 2007
    Location
    0,0,0
    Posts
    913
    Gamer IDs

    Gamertag: BobGneu

    Default

    =) Lets see! I just posted my tutorial on tcplink as well. It is a day for tutorials. =)
    About Me | My Blog | Solarity

    TechnicalHome | ScaleformTechnicalGuide | UnrealScriptReference | ReplicationHome | MasteringUnrealScriptBaptismByFire

    Kismet makes sense to me when i 'read' it seeming mostly logic based

  8. #8
    Marrow Fiend
    Join Date
    Jun 2009
    Posts
    4,479

    Default

    Would it be scaleform or canvas?
    I presume canvas, since you are posting here, which would be awesome.

    But I can't imagine canvas being capabable of moving items around in inventory boxes.
    If you have been able to figure that out, then.. good god I could use this.
    Last edited by Graylord; 09-06-2011 at 06:46 AM.
    Please don't send me private messages asking how to use UDK unless it has to do with my work, everything I can teach is already out there.

    I am not support, I am here to learn myself.

  9. #9
    MSgt. Shooter Person
    Join Date
    Nov 2009
    Posts
    115

    Default

    Count me in. I could certainly use that.

  10. #10

  11. #11
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    I hope you're working hard on that tutorial

    i can't wait

  12. #12
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    Its not a visual inventory, its a base for storing items. The visual can be done with my Canvas tutorial. It should be easy to make dragable buttons.

    Something like "on click" set the position of the button to the position of the arrow while the click is held. etc.

    Should be simple.

    I'm working on the tutorial now : ].

    Tutorial up!!!!
    Last edited by TheAgent; 09-06-2011 at 11:06 AM.

  13. #13
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    i'm gonna try it after i get something to eat

  14. #14
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    all works pretty good.

    I'll try to get my custom weapon in the inventory...
    ill keep you posted

    edit: maybe it's because i've been staring at my screen for over 8 hours today but i get this error and i need a little bit of help



    This error occurs when i walk over my custom weapon (in a weapon pickup) first it says out of bounds (0/0) and then it says (1/0);
    when i try to fire i get another out of bound (0/0)..

    Does anyone have a fix?
    Last edited by Carsten; 09-06-2011 at 02:28 PM.

  15. #15
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    I get that error when i "fire" my weapon. It has to do with the pending fire array in the original Inventory manager.

    I haven't really bothered with a fix yet.

    It's basically saying that your weapon is trying to access something that is not within the 0 or 1 range of the array.

  16. #16
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    but we can't fire our weapons now

  17. #17
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    My inventory shouldn't mess with the original inventory/weapons im not sure how that effects weapons.

  18. #18
    Redeemer
    Join Date
    Jun 2010
    Location
    Barcelona
    Posts
    1,892

    Default

    pretty nice! thanks for this one

    now one question, what's the difference between using this one and the UTInventoryManager with the regular pickup objects? a quick look tells me this one gives HUD messages when you pick an object up, uses inventory spaces, and allows to add gold. anything else I'm missing here?
    I ask because I already have a very basic inventory that extends UTInventoryManager but have some (little) functionality on it, and I'd rather learn what yours does and add up to mine instead of replacing mine entirely

  19. #19
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    It works differently because its not using any UT content. The basic inventory extends actor. So if i just do it extending actor I avoid any unneeded code and starting from the ground up helps built functionality for your project as well as help you understand how the inventory works.

    It just worked better in my case so i did it this way.

  20. #20
    Redeemer
    Join Date
    Jun 2010
    Location
    Barcelona
    Posts
    1,892

    Default

    I guess it does work differently since no UT content was being used. Then again I don't recall my UT-based basic inventory ever using any UT content (or perhaps I got rid of it and I can't remember!), but it certainly has some of that unneeded code.

    anyway I'll take a much more thorough look to see if there's any other extra functionality (besides what I already mentioned) that the UT inventory doesn't have.
    thanks again for the tut

  21. #21
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    any news on how to make our weapon that we get from our new inventory shoot?

  22. #22
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    This inventory has nothing to do with weapons, or UT weapons. So it must be something on your weapon not on my inventory code.

    I have no clue how to really solve that and it might be awhile before i start looking for a solution as i started classes today. However, i really see nothing that will mess with weapons(as there is no connection to them).

    Note : Weekends I may be able to spend some time on it.

  23. #23
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    so this inventory is basically used for picking up custom items and gold?

  24. #24
    Redeemer
    Join Date
    Jun 2010
    Location
    Barcelona
    Posts
    1,892

    Default

    yes. and the UT classes already have an inventory. this is a different approach, probably better aimed for the people not extending from the UT classes. it also has some extra features like gold, and inventory spaces (not visual though)

  25. #25
    Iron Guard
    Join Date
    Jan 2011
    Location
    Netherlands
    Posts
    738
    Gamer IDs

    Gamertag: ColdGuy

    Default

    yeah i dont like to extend the UT classes aswell.

    i feel it gives me alot more room to do things.. but i still need to learn so much

  26. #26
    Redeemer
    Join Date
    Jun 2010
    Location
    Barcelona
    Posts
    1,892

    Default

    yeah its a matter of preference. I prefer to extend from the UT classes because after like 2 months of not doing so initially, I figured I wasted much more time implementing stuff that was already there somewhere, than overriding and removing what I didn't need

    anyway this thread needed a bump since it's a nice tut

  27. #27
    MSgt. Shooter Person
    Join Date
    May 2010
    Posts
    44

    Default

    Bah after implimenting my own version of this I compiled... Worked fine, awesome.
    Changed the static mesh for the 'bag' and the size, rebuild and now it can't find my paths for my project file at all.

    Code:
    Warning: Warning, Failed to load 'SpaceBox': Can't find file for package 'SpaceBox' while loading NULL
    Will go and look at config and the visual studios setup... Wonder why that randomly happened.


    Nvm fixed that. Got quite a few errors after that, however one I question which might seem newbish:

    Within the UHUD

    Code:
    Canvas.Font = PlayerFont; //It is calling the '=' as a bad or missing expression
    Edit:
    So I get rid of that just so I can compile, change the static mesh, works fine, can place it, walk over it.. Nothing happens, I get not on screen messages apart from a '0' that shows very briefly. I will now go away and look into it however any help would be appreciated for a learner.
    Also just to confirm weapons aren't firing at all... Needs support for the weapons perhaps as they were using default inventories.
    Last edited by Jestersheepy; 09-10-2011 at 10:58 AM.

  28. #28
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    I don't know why the weapons don't work. I have my own custom weapon so im not sure why its not working.

    I think i may have missed a few vars.


    For the item make sure that the object has the collision set to touch all.

    Going to check right now.

    Edit:

    Ok add var Font PlayerFont;

    in the HUD i forgot to add that.
    Last edited by TheAgent; 09-10-2011 at 12:05 PM.

  29. #29
    MSgt. Shooter Person
    Join Date
    Dec 2010
    Posts
    56

    Default

    sorry if this obvious, It compiled perfectly (with all the name changing) but how do we see the herb dropped and picked up? Also, can this be integrated with Scaleform easily? I just started UI and this would seem perfect to test and tweak to learn how the inventory system (There's not too many good ones).


    Thanks!

  30. #30

    Default

    Does anyone know if this works with the September + builds of UDK? I am having trouble as well getting this to show up on my screen....

  31. #31
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    Quote Originally Posted by crunx View Post
    sorry if this obvious, It compiled perfectly (with all the name changing) but how do we see the herb dropped and picked up? Also, can this be integrated with Scaleform easily? I just started UI and this would seem perfect to test and tweak to learn how the inventory system (There's not too many good ones).


    Thanks!
    This is theoretical and sightly abstract. You will need to implement physical pick ups and drops yourself. It is meant as a starting point.

    For September I don't know. I haven't tested it. I haven't messed with that code in a while. It could just be that you missed something.

  32. #32
    MSgt. Shooter Person
    Join Date
    Jun 2011
    Posts
    186

    Default

    First of all I would like to thank you for making this, and it has been a great help for me. I am wanting to use it in the game I am making but I am running into a problem when I try to add more functionality.

    For example in the code below I am trying to write a simple HasItem function to search through the inventory to find if the pawn has a certain item in the inventory. When I use this code and try to compile it, it crashes. I am almost positive this is a pretty easy fix but I just can't figure out what I need to change to get it to work how I would like it to.

    Code:
    function bool PawnHasItem(String item1)
    {
    	local int i;
    	
    	for (i = 0; i < MyModularPawn.UInventory.Length; ++i) 
    	{
    		
    		if (item1 == MyModularPawn.UInventory[i].UItems.DisplayName) 
    		{
    		  `log("You Have The Item");
    		  return true;
    		}
    		
    	   return true;
    	
    	}   
    }

  33. #33
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    I technically already have this implemented

    Code:
    for (i=0;i<UItems.Length;i++)
      {
                        //When the iterator reaches a class that macthes the one that you want add it to itemamountininventory
         if (UItems[i].Class == ItemToCheck)
          {
            ItemAmountInInventory ++;
            `log(""@ItemToCheck$" Has"@ItemAmountInInventory$"Items");
          }
    
       }

  34. #34
    MSgt. Shooter Person
    Join Date
    Jun 2011
    Posts
    186

    Default

    Alrighty, thank you. Before I go on I just want to clarify that I am understanding what this code is doing so I will be be able to build off it correctly.


    Code:
    for (i=0;i<UItems.Length;i++)      If I get this correctly, this means the code will go through the whole array in U_Items file which will have all of the pickup items such as U_HerbItem?
      {
                        //When the iterator reaches a class that macthes the one that you want add it to itemamountininventory
         if (UItems[i].Class == ItemToCheck)    if the item to check equals the specific class in the array it will continue
          {
            ItemAmountInInventory ++;
            `log(""@ItemToCheck$" Has"@ItemAmountInInventory$"Items");
          }
    
       }

    I apoligize for this as this is a pretty basic thing, but I am just having a bit of trouble grasping the concept. I am grateful for your help you have given me. Thanks.

  35. #35
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    Yeah the .Class == means it will check against the class you are looking for. The first one it encounters of that type, is the one that it will be referencing/ using etc.

  36. #36
    MSgt. Shooter Person
    Join Date
    Jun 2011
    Posts
    186

    Default

    Alright cool so was I right about how it goes through an array thats in the U_Items Class? If so how do I need to set it up?

    If I am wrong does it automatically just go through all of the classes that are extended from U_Items?

  37. #37
    Palace Guard
    Join Date
    Aug 2008
    Location
    Location,Location
    Posts
    3,719

    Default

    It will go through everything in the array. As long as it extends U_Items.

  38. #38
    MSgt. Shooter Person
    Join Date
    Jun 2011
    Posts
    186

    Default

    The only thing I need to do then is to make the class extend from the U_Items class and then when the code searches for a particular item, the item that I added extending from U_Items automatically is added to the array that the code searches through, right?

    If I am wrong could you please explain it a little more detailed because I am having some major issues getting a grasp of this.

    Thanks again

  39. #39
    MSgt. Shooter Person
    Join Date
    Jan 2012
    Posts
    37

    Default

    Thanks for the tutorial! It is very good. My question is why have a pickup class for your item? Is there anything wrong with having the actual Item class handle the visible mesh and pickups and what not? Thanks.


 

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Copyright ©2009-2011 Epic Games, Inc. All Rights Reserved.
Digital Point modules: Sphinx-based search vBulletin skin by CompletevB.com.