Game Development Community

Scripted Inventory

by Wesley W Frosolone · in Torque Game Engine · 03/02/2004 (7:32 am) · 11 replies

I looked at the various inventory tutorials, and decided that they were not what i needed for my game. So i wrote a new inventory system that takes place entirely in scripts.

When a new player is created, a script object is add to it. This object is their inventory. I wrote several different methods that implement standard linked list functions for this object.

The inventory object has several variables on it, two of which are "pointers" (really just object id numbers..) to the first and last object in the list. Objects added to the inventory get a variable called "next" added to them, which, surprisingly, points to the next object.

The important parts of the code re this:

%player.inventory = new ScriptObject() {
class = Inven;
};

function Inven::storeObj(%this, %obj)
{
....
%this.last.next = %obj;
%this.last = %obj;
....
}

function Inven::getFirst(%this)
{
%this.Position = %this.first;
return %this.Position;
}

function Inven::getNext(%this)
{
%this.Position = %this.Position.next;
return %this.Position;
}


I'm curious as to why i have not turned up anything like this in the forums or the resources. It seems rather trivial over all, and easier to implement then messing with the C++ code. I realize that it will be slower then it would be if implemented on the engine, but so far i have not had any speed issues with it. Is there some reason this would not be an efficient way of doing an inventory that has prevented someone from doing it this way, and posting about it?

I have several other methods written, to search for particular items, and removing items, etc. I also have objects that use this inventory system to store themselves on the player, and to enable the player to activate/deactivate the item.

Should i bother to put together a full resource for this?

#1
03/02/2004 (8:48 am)
I'd say yes, Wesley, make it a resource. (I seem to recall that there is another script based inventory solution around here somewhere, but someone else's take on how to do it is always valuable).
I'm sure many people will find it useful and besides the pure utility of it, may learn something about scripting, or the engine itself, from it.
#2
03/02/2004 (8:53 am)
Im not sure if you guy's have realized or not..
but the current inventory solution is completely script based as well...

:)
there is no c++ code to operate the inventory.
#3
03/02/2004 (9:37 am)
I realize the current one is scripted, but it is too limited.

It uses an array, indexed by datablock names, to record how many instances of a given datablock you have picked up. It was written with the assumption that every item of a given datablock is exactly the same. So if you created an item and made a script object on it, then store it in this inventory system, that script object is gone because it doesn't actually store objects; just the amount of that datablock. If you wanted two different items to use the same datablock, but have different dynamic fields, this inventory is worthless.

Ive looked at all the inventory post and resources i can find, and the best seems to be the Inventory Manager, which is implemented in C++. This is, unfortunately, deficient as well. It uses a linked list, but only stores a few different field for each item. The amount, the name, etc. Since no actual object is stored, this system cannot store items with unique fields.

With the inventory I've implemented, the objects the player has picked up are preserved by linking them together in the linked list, done entirely in the scripts. This allows me to add dynamic fields to items when they are spawned into the world, and maintain those variables after the player has picked them up. Different types of objects can have entirely different fields on them, and when they are returned from the inventory, those fields are available for manipulation.
#4
03/03/2004 (7:27 am)
Please make this a full resource. I am interested in seeing this in context. I had a suspicion that the current ones could be improved a bit, but I am still new to torque, and getting my feet wet.
#5
03/05/2004 (10:05 am)
Same here, would do great as a resource.
#6
04/03/2004 (2:15 am)
Wesley, go for it and make it a resource!
#7
04/03/2004 (11:27 am)
"I realize the current one is scripted, but it is too limited"


I dont see how it is limited. I admit I made some changes to it to expand it's abilities, but if it were limited, I wouldn't have been able to do that. I fail to see what datablocks the current scripted inventory cant save.

Can you give an example of what one of your inventoried items is for comparison?
#8
04/03/2004 (2:47 pm)
Edit: Wrong forums, sorry
#9
06/07/2004 (8:19 pm)
I see this never got resourced, which is too bad unless its on his todo list.

Is something done this way safe from duping/hacking/etc? Is it stored on the server?

I see the script object is added to the player on player creation and that is done in the server/scripts dir but I am still learning precisely on how scoping works.

If doing something this simple realliy does work and is 'safe' then it works well for a prototype if not the real deal!
#10
08/16/2004 (7:20 pm)
Hopefully nobody minds if I re-open this thread, but I figured I'd try to help future script-only-inventory folks. I'm taking a short breather from writing and thought I'd post a bit of code here (which will be in the book, whenever I get done...).

Anyways, enough talk...

@Wesley and others - One difficulty in creating a script only inventory is the fact that (with the current codebase), you cannot get a list of fields in an item, which makes it very hard to faithfully store that information and put it back later when re-creating the 'stored' item.

I've written a bit of code which can be added to gamebase.cc which will dump a list of all fields in the object as a space separated list. I leave it to you to make use of this data, but armed with this list you 'can' devise a way to store the field names and values on a per item basis. Best of luck!

ConsoleMethod( GameBase, getFieldList, const char *, 2, 2, "()"
              "Returns a list of all fields in this object.")
{
	char	*ret;
	char	returnString[4096] = "hello";
	bool	bFoundFields = false;
	int		nLastLength = 0;


	for(int nCount = 0; nCount < 4096; nCount++) returnString[nCount]= '[[6287988824b44]]';


	AbstractClassRep::FieldList fieldList = object->getFieldList();
	AbstractClassRep::FieldList::iterator itr;
	for(itr = fieldList.begin(); itr != fieldList.end(); itr++)
	{
		if(itr->type == AbstractClassRep::DepricatedFieldType)   continue;
		if (itr->type == AbstractClassRep::StartGroupFieldType) continue; 
		if (itr->type == AbstractClassRep::EndGroupFieldType) continue; 

		bFoundFields = true;

		Con::printf("Found field: %s", itr->pFieldname);
		Con::printf("Found field: %s", returnString);
		if(dStrlen(returnString)) {
			nLastLength = dSprintf(returnString, 4096, "%s %s", returnString, itr->pFieldname);
		} else {
			nLastLength = dSprintf(returnString, 4096, "%s", itr->pFieldname);
		}
		

	}

	ret = Con::getReturnBuffer(nLastLength);
	dSprintf(ret, nLastLength, " ");
	if(bFoundFields) {
		dSprintf(ret, nLastLength, "%s", returnString);

	}

	return ret;
}

Note: This code is a bit na
#11
08/16/2004 (8:41 pm)
Actually, anyone who's used NWScript from Neverwinter Nights will recognize the utility in storing data with an item. In a FPS it's hardly important, but in anything with the slightest RPG element in it you'll find ways to put the capability to use. Say, to tag that gun as Bill's gun so that it can be returned to Bill for a reward.

Anyway, great idea. The C++ system could probably be modified to do the same thing, but why do that when it's already done in script (much less chance of breaking anything).

Rich