loading custom car setups
Author: Bernhard Wymann
Description: straight class
Keywords: torcs, berniw, bernhard wymann, car, setup, loading

# 5.2 Loading Custom Car Setups ### Introduction First lets have a look on where the default settings for the cars are coming from. They are loaded automatically from the cars type default settings XML file. These files are located in the cars/* directories, e. g. for the cg-nascar-rwd it is the file cars/cg-nascar-rwd/cg-nascar-rwd.xml (relative to /usr/local/share/games/torcs). This happens always, so if we load no settings ourselves, the default settings are active. If we load a custom setup it just overwrites the default settings, if we don't specify a certain value the default value is active. To create a custom setup we make just a copy of the default setup, remove the stuff we don't want to change and edit the values. ### Loading Setups The following implementation will first try to load a custom car setup for the current track. If there is no such setup available, it falls back to a default custom setup. If this fails also, the TORCS default setup stays active. Our custom setup files will be located e. g. for the driver with index 0 in the subdirectories 0, 0/practice, 0/qualifying and 0/race (relative to the bt directory). Put the following code into driver.cpp, method Driver::initTrack().
    /* Called for every track change or new race. */
    void Driver::initTrack(tTrack* t, void *carHandle, void **carParmHandle, tSituation *s)
    {
        track = t;
First we compute a pointer to the tracks filename from the whole path. The filename starts after the last "/", so we need to add 1 to the location found with strrchr.
        char buffer[256];
        /* get a pointer to the first char of the track filename */
        char* trackname = strrchr(track->filename, '/') + 1;
Depending on the race type, we want to load the fitting setup. For that we assemble the required path to our setup file relative to the /usr/local/share/games/torcs directory.
        switch (s->_raceType) {
            case RM_TYPE_PRACTICE:
                sprintf(buffer, "drivers/bt/%d/practice/%s", INDEX, trackname);
                break;
            case RM_TYPE_QUALIF:
                sprintf(buffer, "drivers/bt/%d/qualifying/%s", INDEX, trackname);
                break;
            case RM_TYPE_RACE:
                sprintf(buffer, "drivers/bt/%d/race/%s", INDEX, trackname);
                break;
            default:
                break;
        }
Now we try to load the setup file. After that we check if the file has been loaded. If not we assemble the path to the default setup file and try to read it. If you are not sure about the setup file name you need for a certain track you can add a printf or cout to print the filename to the terminal.
        *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD);
        if (*carParmHandle == NULL) {
            sprintf(buffer, "drivers/bt/%d/default.xml", INDEX);
            *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD);
        }
    }
Because we haven't created any setups yet the loader will fail for now. In the next section we will create the directory structure for the setups. ### Summary You know where the default setup files are located. You know how to create custom setup files. You have implemented the above setup loader.