Today we are going to look at hash tables.
The comments in fteextensions.qc are pretty clear here, but having it all laid out tutorial style can still be helpful, so here goes.
Code: Select all
hashtable(float tabsize, optional float defaulttype) hash_createtab = #287;
void(hashtable table) hash_destroytab = #288;
void(hashtable table, string name, __variant value, optional float typeandflags) hash_add = #289;
__variant(hashtable table, string name, optional __variant deflt, optional float requiretype, optional float index) hash_get = #290;
__variant(hashtable table, string name) hash_delete = #291;
string(hashtable table, float idx) hash_getkey = #292;
and supported EV_ types
Code: Select all
const float EV_STRING = 1;
const float EV_FLOAT = 2;
const float EV_VECTOR = 3;
const float EV_ENTITY = 4;
const float EV_FIELD = 5;
const float EV_FUNCTION = 6;
const float EV_POINTER = 7;
const float EV_INTEGER = 8;
const float EV_UINT = 9;
const float EV_INT64 = 10;
const float EV_UINT64 = 11;
const float EV_DOUBLE = 12;
and hash table add behaviors
Code: Select all
const float HASH_REPLACE = 256; /* Used with hash_add. Attempts to remove the old value instead of adding two values for a single key. */
const float HASH_ADD = 512; /* Used with hash_add. The new entry will be inserted in addition to the existing entry. */
Hash tables are like dictionaries in python, key value pairs in java, or,
sql tables where every ID is a string, and there is only 1 other column for data.
Hash tables are useful for storing and retrieving data, think loot tables and inventory.
First we declare the hashtable variable as a field, so that we can have 1 per player.
Then we need to call hash_createtab, give it a table size, and tell it what type of values it should accept
Code: Select all
self.inventory = hash_createtab(16, EV_ENTITY);
next, we want to actually store something in the table, so lets find the a healthbox and shove it in our inventory.
we are storing the h_box in our self.inventory, under the key "healthbox", and if we already have something stored under "healthbox", then our item will be replaced.
Code: Select all
entity h_box = find(world, classname, "item_health");
if(h_box != world)
{
hash_add(self.inventory, "healthbox", h_box, HASH_REPLACE);
}
now that we have a healthbox in our inventory, we will want to be able to access it.
so we call hash_get on our self.inventory. and we look up "healthbox", letting hash_get know that we are expecting an EV_ENTITY in return.
Code: Select all
entity default = world;
entity hash_get(self.inventory, "healthbox", optional __variant deflt, EV_ENTITY);
also of interest here, are the arguments deflt and index.
deflt tells hash_add what value we would like returned in the event that the item is NOT found.
for entities, world is the obvious choice, it indicates an error, but say you wanted to grab a weapon, but if that weapon wasnt available you still wanted to equip SOMETHING.
well you could use the deflt field here to say, if you cant find the weapon you are looking for, then just grab me the trusty axe.
Index is a special case, because it isnt useful at all if we are using HASH_REPLACE.
If instead we used HASH_ADD, then we would have multiple entries for the same value, and we could tell it that we wanted the first, second, third, fifth one found in the list
The problem i found with the index value and HASH_ADD, is that while you can add multiple entries to the same key, and retrieve them using the index,
you cant *remove* the items from the hash table using an index. its all or nothing. remove every entry with that key, or leave it be.
This limitation made me decide to not actually use hash tables for inventory for my specific use case, but your case may be a better fit.
now that we have a table, it has something in it, and we know how to retrieve items, its time to wrap things up.
Code: Select all
hash_delete(self.inventory, "healthbox");
will remove the item stored as "healthbox" from your table.
and hash_destroytab will delete the table entirely when you are done with it.
the last function of note is hash_getkey;
I find this function less useful because theres no function to get the length of your table, or the number of entries stored under the same name, so its a bit tricky to use.
but given a hard index into your table, it will give you the key name. in our example that would have been "healthbox" before we deleted the entry and the table entirely.