In GalCiv1/Altarian Prophecy and (for the most part) GalCiv2, we had variables in the Civilization class for both RaceID and PlayerID, but they were generally the same and particularly in GC1, were used interchangeably. This was not a problem because there was no multiplayer, and we never had more races defined than the possible number of players. When I was transferring the code from GC1/AP to GC2 and cleaning it up, I made sure that they were distinct; we wanted to leave the option for adding multiplayer at a later date. Over time, little inaccuracies were slipped in, unnoticed, because in GC2 the RaceID was still equal to the PlayerID. Last week, I had spent time going through and trying to find these, mainly by searching all of our code files for relevant variable and function names. This week, I actually changed the function that creates the civilization and sets its race and playerID.
The PlayerID is the unique number that is used to identify a civilization/player without needing to know race-specific information. It's used to identify who owns planets and ships, among other things, and also serves as a way to order the civilizations. The RaceID is more subtle. It's used to identify which song to play when you're speaking to a given civ, and in the AI code to make the AI behave in certain ways. For example, in the AI relations code, it's important to know which civ is the race Drengin, and which civ is the race Torian, since they have a history of animosity. For the most part, the RaceID is only important to the major races, but the Pirates and Dread Lords are considered minor races, but they need to know theirs. So I was in a quandary; I didn't want to make the custom opponents have to use the same RaceID as one of the existing races, (because then they would act like the Drengin, etc) but if I just started at an arbitrary number and incremented it, I wouldn't be able to tell from the number of the RaceID if it was a major or minor race.
I ended up deciding that the RaceIDs for the current races would stay the same, and the custom races would all use the constant RACE_CUSTOM. That way, they wouldn't act like one of the existing races, and I would be able to tell that they were a major race from the RaceID still. I've been adding fields to the raceconfig format so that things like the robot image are no longer strings generated by a generic name and the race number, so you'll still be able to specify your own images, etc for your custom race. Also, I am changing the file extension from .raceconfig to .customrace because it is more descriptive and it will ensure that people are starting with clean files when they install Dark Avatar.
Since the RaceIDs were no longer going to be tied to the order they were read in from the RaceConfigXML file, I had to make the custom star systems work in any order, too. When I had first written the custom star system code, I was in a hurry, which was one of the reasons that they had to be in a specific order. I had made it so that when the planets were being placed, it picked the star systems for 11 possible races first, and created them using the definitions from the customplanets xml file. This happened before the player race or opponents were setup, so it would just create all of the custom planets and then randomize any unnecessary systems. However, that wasn't going to work for Dark Avatar with the custom opponents. So I changed it so that it still picked 11 star systems, but now it just automatically creates 5 class 0 planets in the 11 star systems. Then, when the civilizations are created, it uses the custom star system definition to turn the 'blank' star system in to the Sol system, or the Drengia system, etc. (hiding any extraneous planets in the system) and the unused ones are still randomized. If it can't find a star system using the star name in the file, it looks for a star system definition containing the homeworld name. If all else fails, it will use the race ID to get the default definition of the system and rename the star and planets accordingly. If things go really wrong, it can still grab another planet and increase the PQ of one of them to be high enough, however at that point you'd have had to delete your custom planets file, which would trip the metaverse cheater flag.
I was able to start a game in Dark Avatar and play for awhile today, so I've caught some of the bugs caused by the change in the PlayerID/RaceID code. I think that I've got all the major functionality of it working, so I just have to go through all the screens and make sure that they are using the PlayerID and RaceID where appropriate. At the moment, I'm working on the save games to make sure that I'm saving and restoring all the necessary information. It's rather tedious, as it means saving a game, loading it to see if it actually loads, and then seeing if I can find anything that's broken. Save games, by the way, will not be compatible between Dark Avatar and older versions. There is too much missing info that I would have to extrapolate.
Next week, I am going to have to do a lot of testing, mostly playing the game trying to find stuff that is not displaying correctly (or causes crashes) because it's using a PlayerID instead of RaceID (or vice versa). I'll also have to make certain that the Dread Lords campaign still works, and I'll probably also check to see if it will handle the addition of the Dark Avatar campaign while I'm in that code anyway. I also haven't tested playing against any made-from-scratch custom opponents yet; in my test game, I just made sure that the civs I picked would have PlayerIDs that were different from their RaceIDs.
It is, however, going to be a short week because I am going to be a guest speaker at Dragon*Con this year!