If you want to try and write some custom QC, there's a bit of a snag trying to do it exactly the way that stock Quake does it. The tracking uses a variable called
serverflags which is updated when you collect a rune, and carries from level to level. The func_episodegate reads this value when it spawns and deletes itself if the right value has not yet been set. The problem is that the same global also causes the runes to be drawn on the HUD.
So you're better off creating your own global to track what's been done in your maps. The trick now is figuring how to transfer the value between maps. To my mind the best way to do it is to use the parm values in SetChangeParms to smuggle a value from map to map. Look at the functions in SetChangeParms and DecodeLevelParms in client.qc to see how they work now. Currently they send information about the items and health each player has; by storing it more efficiently you can free up space for your global.
This actually seems like it would make for a good blog post, and I've been looking for something shorter to write while other stuff comes together, so I won't go into more detail on that option at this time...
The other option is to use the built-in features of Quoth to do the same: the Session Mapindex. Unfortunately the documentation of this feature is badly organised as it's spread amongst three entity entries. I need to write a linking topic.
The feature starts with modification of
http://tomeofpreach.wordpress.com/quoth/tutorial/trigger_changelevel/
In Quoth the "Session Mapindex" is a counter that is preserved across level transitions. If you set a "mapindex" key on the changelevel trigger, when the player exits through that trigger, the value is added to the counter.
To use the counter, you need to be able to detect it. The following entities are conditional triggers which may or may not fire according to the value the counter holds at the start of the map.
http://tomeofpreach.wordpress.com/quoth/tutorial/info_mapgate/
To understand the difference, it's worth getting into how bitflags work. The best values to use are the powers of 2:
1, 2, 4, 8, 16, 32...
The reason these values work so well is that if you take one of each value, the sum of any subset can never equal any other member of the set. We can use this in reverse: give each map a different value from the set, and we can work out which individual maps have been completed, given only the sum of them. (The other reason that bitflags are a nice set of value to use is that EVERY number can be created as a combination of them)
The info_mapgate needs a mapindex key, which we should think of as a sum of bitflags. If
any of the bitflags it includes are also in the "Session Mapindex" counter then the trigger fires. The easiest way to use this is to just set mapindex to a single bitflag, which gives you a trigger which fires when a particular map is completed. You can also set the first spawnflag on this info_mapgate; then it only fire when the map is NOT completed, which makes it easy to killtarget a door entity.
Lastly, you might want to detect when ALL of the maps are completed. For this you need an info_endgate:
http://tomeofpreach.wordpress.com/quoth/tutorial/info_endgate/
This works in a similar way, but rather than setting which bitflag you want, you only specify how many bitflags it covers, for example if you set "mapindex" "4" it detects if all the flags 1 + 2 + 4 + 8 = 15 are present in the counter. It's a bit of a weird interface, but for making a basic hub it works well.