# Storing items in external data files

My project, in its current state, keeps all of the info for each inventory item in script files. That means, inventory items and their properties are part of the codebase. This works well, but I'm advancing quickly through development and I fear that this system is going to pose some problems later on. Normally, data (item properties) are not stored in the code, but in some sort of database.

I was thinking about storing item properties in external (text for now) data files, that would get parsed when the game loads. I'd mark each item with a string ID (for easier referencing in other places - GetItemWithID("FOOD_FISH") makes more sense than GetItemWithID(5)). Then, I'd build some sort of class that would take care of item-driven events (such as what happens when an item is consumed). Then I'd map each function implemented by the manager to some interpretable string counterpart (in an item's data file I'd have the string "RestoreHealth(50)" - this would be mapped by the manager to the function RestoreHealth (the param would get passed too)).

Is this an even remotely good idea? How would you do it?

Another thing that I'm thinking of, since I'm building a tool to make inventory item creation easier, is to develop something that simply generates appropriate C# code for an underlying database of user-readable and editable item properties.

E.g. it takes in

FOOD_FISH
Name:Fish
Value:50
OnConsume:
RestoreHealth(40)


and generates

FoodFish = new InventoryItem();
//Properties set here.


LATER EDIT:

After Byte56's reply, I came up with a kind of format that's easy enough to parse.

[ID:IT_FO_TROUT]
[Name:Trout]
[Description:A raw trout.]
[Value:10]

[3DModel:null]
[InventoryIcon:trout]

[Tag:Consumable]
[Tag:Food]
[Tag:Stackable]

[OnConsume:RestoreHealth(15)]
[OnConsume:RestoreFatigue(15)]


Since on the project there will be people with no programming experience working remotely, using external files + custom item generators seems to be the best way to go. Should've figured it out earlier.

• I prefer XML files myself, but whatever is easiest for you to parse should work just fine. Jan 26, 2013 at 0:43
• I find that parsing using simple string functions is much nicer. At least during development :)
– user15805
Jan 26, 2013 at 16:41

Yes, storing the items in external files is a good idea. I created something very close to what you're talking about. It's an item/entity lexicon. Items, materials and entities are all stored in this "database". The script files get read on load and store every item available in game.

You can see kind of an example of what the entity files look like here.

The format of the script is up to you. You may want to use XML or some other common script, or you can make your own like I did or what it looks like you've started to do.

When the items are read in, they go into an item blueprint class. This class has all the required information for generating a new item. It also allows each item some variation. As you can see in my other answer, I define ranges of acceptable values. When the item is created it will choose a random value from within the range defined, giving each item a slightly different quality/value/whatever.

All those blueprints are stored in a HashMap, a Dictionary for C#. The ID is the key and the value is the blueprint. I also have the keys in a HashMap that's referenced by the item name. This makes it easier for me if I want to create a specific item, and I don't remember the name. For example I have an apple defined:

MATERIAL:"Apple" {
description="An apple, a tasty fruit"
commonName="Apple"
pluralCommonName="Apples"
tags=Fruit,Edible
basetype=CulinaryFruit
qualityrange=0.2:1.0
itemtextureindex=10
value=15
density=20.0
entityBaseAttributes="Small Physics Item","Slow Decay"

HarvestItems{
HarvestItem{
material="Apple seed"
TimeToCollect=200:500
WeightedChance=1
MinConditionToProduce=0.3
OverrideQuality=1.0:1.0
}
HarvestItem{
material="Apple core"
TimeToCollect=200:500
WeightedChance=1
MinConditionToProduce=0.3
}
}
}


Where Apple seed and Apple core are also items defined in the script. So if I want to create an apple somewhere, I have a method that takes the information above and generates the properties of an entity. Including some predefined standards like "Small Physics Item" and "Slow Decay" which add attributes to the entity being generated.

It's a pretty flexible system that allows me to quickly generate new items. And it's easy to use, because I don't actually even need to know the IDs of anything, I can reference them by name. I also have an entity named "Apple Tree" that has a ProduceItems attribute that generates Apple.

All in all, yes, it's a good idea to put your items in scripts. And with a little work, you can create some very complex behaviors and items with your item scripts.

• This gives me some ideas! Especially the one about making the same item available via name as well as ID. Yeah, I guess storing them in files is a better idea, even though I have to do some parsing. Your entity reply also gave me some ideas on how to store NPCs and dialogues. That's the next step. I'll come with an edit to my original post and accept the answer.
– user15805
Jan 25, 2013 at 23:04
• Nice I'm glad that's useful. I'm still developing the format as I go, but it's nice to have a solid base. Your new format looks nice, and I think it'll work well for you.
– House
Jan 25, 2013 at 23:09
• Just one more question: you can notice I also entered identifiers for functions that must be called when the item is consumed. How would you approach this: every time the item is consumed, parse the string identifiers for the funcs and call their counterparts, or just use a list of pointers to functions (delegates) per each item, and call each function in the list when the item gets consumed? The 2nd way is more efficient, since you only do the parsing once, but passing parameters will be a pain that way (when parsing strings this problem is not present, since the params are there).
– user15805
Jan 25, 2013 at 23:12
• e.g: 1st way - foreach string s in (string identifiers for functions in OnConsume): func = Parser.GetFunc(s), params = Parser.GetParams(s); call func(params).
– user15805
Jan 25, 2013 at 23:14
• would like to add here that if you create an interface and allow your data loaders implement it that way if you wish to change your format only have to create a new loader. Jan 25, 2013 at 23:33