// Save the choosen values in the corresponding parameter file. static void saveSoundOption(void *) { const int BUFSIZE = 1024; char buf[BUFSIZE]; snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GR_SOUND_PARM_CFG); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); GfParmSetStr(paramHandle, GR_SCT_SOUND, GR_ATT_SOUND_STATE, soundOptionList[curOption]); GfParmSetNum(paramHandle, GR_SCT_SOUND, GR_ATT_SOUND_VOLUME, "%", VolumeValue); GfParmWriteFile(NULL, paramHandle, "sound"); GfParmReleaseHandle(paramHandle); // Write Menu music optons snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), MM_SOUND_PARM_CFG); paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); GfParmSetStr(paramHandle, MM_SCT_SOUND, MM_ATT_SOUND_ENABLE, menuMusicList[curOptionMenuMusic]); GfParmWriteFile(NULL, paramHandle, "sound"); GfParmReleaseHandle(paramHandle); if (curOptionMenuMusic == 1) { startMenuMusic(); } else { stopMenuMusic(); } // Return to previous screen. GfuiScreenActivate(prevHandle); return; }
// Write parameter meta data to xml file int TGeneticParameter::Set(const char* Part, int Index) { char ParamSection[64]; if (Part == NULL) sprintf(ParamSection,"%s/%d",SECT_GLOBAL,Index); else sprintf(ParamSection,"%s/%d",Part,Index); GfParmSetNum(Handle, ParamSection, PRM_ACTIVE, 0, (float) Active); if (LeftRight) { if (SameSign) GfParmSetNum(Handle, ParamSection, PRM_TWOSIDE, 0, 1); else GfParmSetNum(Handle, ParamSection, PRM_TWOSIDE, 0, -1); } else GfParmSetNum(Handle, ParamSection, PRM_TWOSIDE, 0, 0); GfParmSetStr(Handle, ParamSection, PRM_LABEL, Label); GfParmSetStr(Handle, ParamSection, PRM_SECT, Section); GfParmSetStr(Handle, ParamSection, PRM_PRM, Parameter); GfParmSetStr(Handle, ParamSection, PRM_UNIT, Unit); GfParmSetNum(Handle, ParamSection, PRM_RANGE, Unit, Val, Min, Max); GfParmSetNum(Handle, ParamSection, PRM_WEIGHT, 0, Weight); GfParmSetNum(Handle, ParamSection, PRM_SCALE, 0, Scale); GfParmSetNum(Handle, ParamSection, PRM_ROUND, 0, Round); return 0; };
static bool gfFileSetupCopy( char* dataLocation, char* localLocation, int major, int minor, void *localHandle, int count ) { bool status; // Copy the source file to its target place. if( !( status = GfFileCopy( dataLocation, localLocation ) ) ) return status; // Update local version.xml file. if( localHandle ) { if( count < 0 ) { GfParmSetCurStr( localHandle, "versions", "Data location", dataLocation ); GfParmSetCurStr( localHandle, "versions", "Local location", localLocation ); GfParmSetCurNum( localHandle, "versions", "Major version", NULL, (tdble)major ); GfParmSetCurNum( localHandle, "versions", "Minor version", NULL, (tdble)minor ); } else { char buf[32]; snprintf( buf, 30, "versions/%d", count ); GfParmSetStr( localHandle, buf, "Data location", dataLocation ); GfParmSetStr( localHandle, buf, "Local location", localLocation ); GfParmSetNum( localHandle, buf, "Major version", NULL, (tdble)major ); GfParmSetNum( localHandle, buf, "Minor version", NULL, (tdble)minor ); } } return status; }
// Save the choosen values in the corresponding parameter file. static void saveSoundOption(void *) { // Force current edit to loose focus (if one has it) and update associated variable. GfuiUnSelectCurrent(); char buf[1024]; sprintf(buf, "%s%s", GfLocalDir(), SND_PARAM_FILE); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); GfParmSetStr(paramHandle, SND_SCT_SOUND, SND_ATT_SOUND_STATE, soundOptionList[curOption]); GfParmSetNum(paramHandle, SND_SCT_SOUND, SND_ATT_SOUND_VOLUME, "%", VolumeValue); GfParmSetStr(paramHandle, SND_SCT_MUSIC, SND_ATT_MUSIC_STATE, musicStateList[curMusicState]); GfParmSetNum(paramHandle, SND_SCT_MUSIC, SND_ATT_MUSIC_VOLUME, "%", MusicVolumeValue); GfParmWriteFile(NULL, paramHandle, "sound"); GfParmReleaseHandle(paramHandle); // Shutdown the user interface. LegacyMenu::self().shutdown(); // Restart the game. GfuiApp().restart(); // Return to previous screen. GfuiScreenActivate(prevHandle); }
// Write meta data of part to xml file int TGeneticParameterPart::Set(int Index) { char ParamSection[64]; sprintf(ParamSection,"%s/%d/%s",SECT_LOCAL,Index,SECT_DEFINE); GfParmSetNum(Handle, ParamSection, PRM_ACTIVE, 0, (float) Active); GfParmSetStr(Handle, ParamSection, PRM_NAME, Label); GfParmSetStr(Handle, ParamSection, PRM_SECT, Section); GfParmSetStr(Handle, ParamSection, PRM_SUBSECT, Subsection); GfParmSetStr(Handle, ParamSection, PRM_PRM, Parameter); return 0; };
void rmtsSelect(void * /* dummy */) { int curTrkIdx; const int BUFSIZE = 1024; char path[BUFSIZE]; curTrkIdx = (int)GfParmGetNum(ts->param, RM_SECT_TRACKS, RE_ATTR_CUR_TRACK, NULL, 1); snprintf(path, BUFSIZE, "%s/%d", RM_SECT_TRACKS, curTrkIdx); GfParmSetStr(ts->param, path, RM_ATTR_CATEGORY, CategoryList->name); GfParmSetStr(ts->param, path, RM_ATTR_NAME, ((tFList*)CategoryList->userData)->name); rmtsDeactivate(ts->nextScreen); }
/* Save the choosen values in the corresponding parameter file */ static void storeSimuCfg(void * /* dummy */) { char buf[1024]; snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); GfParmSetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[CurSimuVersion]); GfParmSetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_MULTI_THREADING, MultiThreadSchemeList[CurMultiThreadScheme]); GfParmSetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_THREAD_AFFINITY, ThreadAffinitySchemeList[CurThreadAffinityScheme]); GfParmWriteFile(NULL, paramHandle, "raceengine"); GfParmReleaseHandle(paramHandle); /* return to previous screen */ GfuiScreenActivate(PrevScrHandle); return; }
void NetServer::GenerateDriversForXML() { assert(m_strRaceXMLFile!=""); void *params = GfParmReadFileLocal(m_strRaceXMLFile.c_str(),GFPARM_RMODE_STD); assert(params); const char *pName =GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, ""); int nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); //Gather vector of all non human drivers std::vector<NetDriver> vecRDrivers; for (int i=1;i<=nCars;i++) { NetDriver driver; ReadDriverData(driver,i,params); if (strcmp(driver.module,NETWORKROBOT) && strcmp(driver.module,HUMANROBOT)) vecRDrivers.push_back(driver); } //Recreate drivers section robots first char drvSec[256]; GfParmListClean(params, RM_SECT_DRIVERS); for (int i=0;i<(int)vecRDrivers.size();i++) { int index = i+1; sprintf(drvSec, "%s/%d", RM_SECT_DRIVERS, index); GfParmSetNum(params, drvSec, RM_ATTR_IDX, (char*)NULL, (tdble)vecRDrivers[i].idx); GfParmSetStr(params, drvSec, RM_ATTR_MODULE, vecRDrivers[i].module); } //And then add the networkhuman drivers NetServerMutexData *pSData = LockServerData(); for (int i=0;i<(int)pSData->m_vecNetworkPlayers.size();i++) { int index = i+1+vecRDrivers.size(); sprintf(drvSec, "%s/%d", RM_SECT_DRIVERS, index); GfParmSetNum(params, drvSec, RM_ATTR_IDX, (char*)NULL,(tdble) pSData->m_vecNetworkPlayers[i].idx); GfParmSetStr(params, drvSec, RM_ATTR_MODULE, pSData->m_vecNetworkPlayers[i].module); } UnlockServerData(); //Save our changes GfParmWriteFileLocal(m_strRaceXMLFile.c_str(), params, pName); }
void RaceSet::genXML(){ std::string path = xmlFolder+"quickrace"+std::to_string(carQty)+".xml"; void *parmHandle = GfParmReadFile(path.c_str(), GFPARM_RMODE_CREAT); int ret =mkdir(folder.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if(ret<0&&errno!=EEXIST){ std::cout<<"Race failed: Unable to access xml directory"<<std::endl; throw 1; } for(int i=0;i<qty;i++){ GfParmSetNum(parmHandle, "Quick Race", "laps", NULL, races[i].laps); GfParmSetNum(parmHandle, "Quick Race", "distance", NULL, races[i].distance); GfParmSetStr(parmHandle, "Tracks/1", "name", races[i].track.c_str()); GfParmSetStr(parmHandle, "Tracks/1", "category", races[i].category.c_str()); GfParmWriteFile((folder+"r"+std::to_string(i)+".xml").c_str(), parmHandle, NULL); } }
// Write table of content to configuration file int TGeneticParameterTOC::Set() { GfParmSetStr(Handle, SECT_TOC, PRM_AUTHOR, Author); GfParmSetStr(Handle, SECT_TOC, PRM_PRIVATE, Private); GfParmSetNum(Handle, SECT_TOC, PRM_LOOPS, 0, (float) OptimisationLoops); GfParmSetNum(Handle, SECT_TOC, PRM_DAMAGES, 0, (float) WeightOfDamages); if (GetInitialVal) GfParmSetNum(Handle, SECT_TOC, PRM_INITIAL, 0, 1); else GfParmSetNum(Handle, SECT_TOC, PRM_INITIAL, 0, 0); return 0; };
void NetServer::SetHostSettings(const char *pszCarCat,bool bCollisions) { assert(m_strRaceXMLFile!=""); void *params = GfParmReadFileLocal(m_strRaceXMLFile.c_str(),GFPARM_RMODE_STD); assert(params); const char *pName =GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, ""); GfParmSetStr(params, RM_SECT_HEADER,RM_ATTR_CAR_CATEGORY, pszCarCat); GfParmWriteFileLocal(m_strRaceXMLFile.c_str(), params, pName); }
static void rmdsSetFocus(void * /* dummy */) { char *name; tDrvElt *curDrv; name = GfuiScrollListGetSelectedElement(scrHandle, selectedScrollList, (void**)&curDrv); if (name) { GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, curDrv->dname); GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, curDrv->index); GfuiLabelSetText(scrHandle, FocDrvLabelId, curDrv->name); } }
/* Save the choosen values in the corresponding parameter file */ static void SaveSimuVersion(void * /* dummy */) { char buf[1024]; snprintf(buf, 1024, "%s%s", GetLocalDir(), RACE_ENG_CFG); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); GfParmSetStr(paramHandle, "Modules", "simu", simuVersionList[curVersion]); GfParmWriteFile(NULL, paramHandle, "raceengine"); GfParmReleaseHandle(paramHandle); /* return to previous screen */ GfuiScreenActivate(prevHandle); return; }
// Save the choosen values in the corresponding parameter file. static void saveSoundOption(void *) { char buf[1024]; sprintf(buf, "%s%s", GetLocalDir(), GR_SOUND_PARM_CFG); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); GfParmSetStr(paramHandle, GR_SCT_SOUND, GR_ATT_SOUND_STATE, soundOptionList[curOption]); GfParmSetNum(paramHandle, GR_SCT_SOUND, GR_ATT_SOUND_VOLUME, "%", VolumeValue); GfParmWriteFile(NULL, paramHandle, "sound"); GfParmReleaseHandle(paramHandle); // Return to previous screen. GfuiScreenActivate(prevHandle); return; }
static void rmrpValidate(void * /* dummy */) { if (rp->confMask & RM_CONF_RACE_LEN) { rmrpUpdDist(0); rmrpUpdLaps(0); GfParmSetNum(rp->param, rp->title, RM_ATTR_DISTANCE, "km", rmrpDistance); GfParmSetNum(rp->param, rp->title, RM_ATTR_LAPS, (char*)NULL, rmrpLaps); } if (rp->confMask & RM_CONF_DISP_MODE) { GfParmSetStr(rp->param, rp->title, RM_ATTR_DISPMODE, rmCurDispModeList[rmCurDispMode]); } rmrpDeactivate(rp->nextScreen); }
void ReEventInitResults(void) { int nCars; int i; void *results = ReInfo->results; void *params = ReInfo->params; const int BUFSIZE = 1024; char path[BUFSIZE], path2[BUFSIZE]; nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); for (i = 1; i < nCars + 1; i++) { snprintf(path, BUFSIZE, "%s/%s/%d", ReInfo->track->name, RM_SECT_DRIVERS, i); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS, i); GfParmSetStr(results, path, RE_ATTR_DLL_NAME, GfParmGetStr(params, path2, RM_ATTR_MODULE, "")); GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, GfParmGetNum(params, path2, RM_ATTR_IDX, (char*)NULL, 0)); } }
bool RobotXml::CreateRobotFile(const char*pRobotName,std::vector<NetDriver> &vecDrivers) { char buf[255]; sprintf(buf,"drivers/%s/%s.xml",pRobotName,pRobotName); void *params = GfParmReadFileLocal(buf,GFPARM_RMODE_CREAT); //Erase existing robots GfParmListClean(params, "Robots"); char path2[256]; for (int i=0;i<(int)vecDrivers.size();i++) { sprintf(path2, "Robots/index/%d",i+1); GfParmSetStr(params, path2, "name",vecDrivers[i].name); GfParmSetStr(params, path2, "car name",vecDrivers[i].car); GfParmSetNum(params, path2, "race number", (char*)NULL,(tdble) vecDrivers[i].racenumber); GfParmSetNum(params, path2, "red", (char*)NULL, vecDrivers[i].red); GfParmSetNum(params, path2, "green", (char*)NULL, vecDrivers[i].green); GfParmSetNum(params, path2, "blue", (char*)NULL, vecDrivers[i].blue); GfParmSetStr(params, path2, "type",vecDrivers[i].type); GfParmSetStr(params, path2, "skill level",vecDrivers[i].skilllevel); GfParmSetStr(params, path2, "networkrace","yes"); if (vecDrivers[i].client) GfParmSetStr(params, path2, "client","yes"); else GfParmSetStr(params, path2, "client","no"); char hostName[256]; enet_address_get_host_ip (&vecDrivers[i].address,hostName,256); GfParmSetStr(params, path2, "host",hostName); GfParmSetNum(params, path2, "port",(char*)NULL, vecDrivers[i].address.port); } //Save our changes GfParmWriteFileLocal(buf, params, pRobotName); GfParmReleaseHandle(params); return true; }
static void rmdsSelect(void * /* dummy */) { char *name; tDrvElt *curDrv; int index; sprintf(buf, "%s", RM_SECT_DRIVERS); GfParmListClean(ds->param, buf); name = GfuiScrollListExtractElement(scrHandle, selectedScrollList, 0, (void**)&curDrv); index = 1; while (name != NULL) { sprintf(buf, "%s/%d", RM_SECT_DRIVERS, index); GfParmSetNum(ds->param, buf, RM_ATTR_IDX, (char*)NULL, curDrv->index); GfParmSetStr(ds->param, buf, RM_ATTR_MODULE, curDrv->dname); index++; name = GfuiScrollListExtractElement(scrHandle, selectedScrollList, 0, (void**)&curDrv); } rmdsDeactivate(ds->nextScreen); }
// Save the choosen values in the corresponding parameter file. static void saveOpenGLOption(void *) { const int BUFSIZE = 1024; char buf[BUFSIZE]; snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GR_PARAM_FILE); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); // Texture compression. GfParmSetStr(paramHandle, GR_SCT_GLFEATURES, GR_ATT_TEXTURECOMPRESSION, textureCompressOptionList[curOptionTextComp]); // Texture sizing. GfParmSetNum(paramHandle, GR_SCT_GLFEATURES, GR_ATT_TEXTURESIZE, (char*)NULL, (tdble) textureSizeOptionList[curOptionTextSize]); GfParmWriteFile(NULL, paramHandle, "graph"); GfParmReleaseHandle(paramHandle); // Return to previous screen. GfuiScreenActivate(prevHandle); updateCompressARBEnabled(); updateUserTextureMaxSize(); return; }
void ReEventInitResults(void) { void *results = ReInfo->results; void *params = ReInfo->params; const int nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); for (int i = 1; i < nCars + 1; i++) { snprintf(path, sizeof(path), "%s/%s/%d", ReInfo->track->name, RM_SECT_DRIVERS, i); snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS, i); GfParmSetStr(results, path, RE_ATTR_DLL_NAME, GfParmGetStr(params, path2, RM_ATTR_MODULE, "")); GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, GfParmGetNum(params, path2, RM_ATTR_IDX, (char*)NULL, 0)); GfParmSetNum(results, path, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path2, RM_ATTR_EXTENDED, (char*)NULL, 0)); //GfParmSetStr(results, path, ROB_ATTR_NAME, // GfParmGetStr(params, path2, ROB_ATTR_NAME, "")); //GfParmSetStr(results, path, ROB_ATTR_CAR, // GfParmGetStr(params, path2, ROB_ATTR_CAR, "")); } }
/* return state mode */ int ReRaceStart(void) { char path[128]; char path2[128]; const char *sessionName = ReInfo->_reRaceName; void *params = ReInfo->params; void *results = ReInfo->results; int mode = 0; // Trace race session identification (more to say for the Carer mode). char pszSessionId[128]; if (!strcmp(GfParmGetStr(ReInfo->mainParams, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO), RM_VAL_YES)) { const char* pszGroup = GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, "<no group>"); snprintf(pszSessionId, sizeof(pszSessionId), "%s %s %s", ReInfo->_reName, pszGroup, sessionName); } else snprintf(pszSessionId, sizeof(pszSessionId), "%s %s", ReInfo->_reName, sessionName); GfLogInfo("Starting %s session at %s\n", pszSessionId, ReInfo->track->name); // Reallocate and reset car info for the race. FREEZ(ReInfo->_reCarInfo); ReInfo->_reCarInfo = (tReCarInfo*)calloc(GfParmGetEltNb(params, RM_SECT_DRIVERS), sizeof(tReCarInfo)); ReUI().onRaceInitializing(); // Drivers starting order int nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); GfParmListClean(params, RM_SECT_DRIVERS_RACING); if (nCars == 0) { // This may happen, when playing with the text-only mode, // and forgetting that human are automatically excluded then, // or when getting back to the GUI mode, and not reconfiguring the competitors list. GfLogError("No competitor in this race : cancelled.\n"); mode = RM_ERROR; } else if ((ReInfo->s->_raceType == RM_TYPE_QUALIF || ReInfo->s->_raceType == RM_TYPE_PRACTICE) && ReInfo->s->_totTime < 0.0f /* Timed session? */) //Checks if there is only one driver per session allowed, so practice, qualification without timed session. { // non-timed Qualification or Practice session => 1 driver at a time = the "current" one. int nCurrDrvInd = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1); if (nCurrDrvInd == -1) return RM_ERROR; // Propagate competitor drivers info to the real race starting grid snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS, nCurrDrvInd); snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, 1); GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RM_ATTR_MODULE, "")); GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0)); GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path, RM_ATTR_EXTENDED, NULL, 0)); GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, NULL, 0)); if (GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0)) GfParmSetStr(params, path2, RM_ATTR_SKINNAME, GfParmGetStr(params, path, RM_ATTR_SKINNAME, "")); } else { // For a race, add cars to the starting grid in the order stored in ReStartingOrderIdx. ReUI().addLoadingMessage("Preparing Starting Grid ..."); int maxCars = (int)GfParmGetNum(params, sessionName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); int currDriver = -1; int aCars = 0; for (int i = 1; i < nCars + 1; i++) { currDriver = ReStartingOrderIdx[i-1]; if (currDriver == -1) continue; aCars++; snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS, currDriver); snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, i); GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RE_ATTR_MODULE, "")); GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RE_ATTR_IDX, NULL, 0)); GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path, RM_ATTR_EXTENDED, NULL, 0)); GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, NULL, 0)); if (GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0)) GfParmSetStr(params, path2, RM_ATTR_SKINNAME, GfParmGetStr(params, path, RM_ATTR_SKINNAME, "")); } //no valid drivers present in the list if (aCars == 0) { GfLogError("No competitor in this race : cancelled.\n"); mode = RM_ERROR; } } //ReTrackUpdate(); if (!(mode & RM_ERROR)) { // According to what the UI answers, start the race right now or not. mode = RM_ASYNC | RM_NEXT_STEP; const bool bGoOn = ReUI().onRaceStarting(); if (bGoOn) mode = ReRaceRealStart(); } return mode; }
int ReRaceEventShutdown(void) { char buf[64]; int curTrkIdx; void *params = ReInfo->params; int nbTrk; void *results = ReInfo->results; int curRaceIdx; bool careerMode = false; bool first = true; // Notify the UI that the race event is finishing now. ReUI().onRaceEventFinishing(); // Shutdown track-physics-related stuff. ReTrackShutdown(); // Determine the track of the next event to come, if not the last one // and, if Career mode, prepare race params / results for the next event or season. do { nbTrk = GfParmGetEltNb(params, RM_SECT_TRACKS); curRaceIdx =(int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1); curTrkIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1); if (curRaceIdx == 1) { if (curTrkIdx < nbTrk) { // Next track. curTrkIdx++; } else if (curTrkIdx >= nbTrk) { // Back to the beginning. curTrkIdx = 1; } } GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, (tdble)curTrkIdx); // Career mode. if (!strcmp(GfParmGetStr(ReInfo->mainParams, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO), RM_VAL_YES)) { careerMode = true; const bool lastRaceOfRound = strcmp(GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_LASTSUBFILE, RM_VAL_YES), RM_VAL_YES) == 0; // Previous file <= Current file. GfParmSetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_PREV_FILE, GfParmGetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, "")); // Current file <= Next file. GfParmSetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_NEXTSUBFILE, "")); GfParmWriteFile(NULL, ReInfo->mainResults, NULL); /* Check if the next competition has a free weekend */ if( !first ) { /* Close old params */ GfParmWriteFile( NULL, results, NULL ); GfParmReleaseHandle( results ); GfParmReleaseHandle( params ); }//if !first /* Open params of next race */ params = GfParmReadFile( GfParmGetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, "" ), GFPARM_RMODE_STD ); if( !params ) break; results = GfParmReadFile( GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_RESULTSUBFILE, ""), GFPARM_RMODE_STD ); if( !results ) { GfParmReleaseHandle( results ); break; } if (lastRaceOfRound && curTrkIdx == 1) { ReCareerNextSeason(); } if ((int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1) == 1) { GfParmListClean(results, RE_SECT_STANDINGS); GfParmWriteFile(NULL, results, NULL); } /* Check if it is free */ snprintf( buf, sizeof(buf), "%s/%d", RM_SECT_TRACKS, (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1) ); if( !strcmp(GfParmGetStr(params, buf, RM_ATTR_NAME, "free"), "free") == 0) { /* Not a free weekend */ GfParmReleaseHandle( results ); GfParmReleaseHandle( params ); break; } first = false; } else { // Normal mode (no subfiles, so free weekends possible, so nothing to check) break; } } while( true ); // Determine new race state automaton mode. int mode = (curTrkIdx != 1 || careerMode) ? RM_NEXT_RACE : RM_NEXT_STEP; bool careerNonHumanGroup = careerMode && !ReHumanInGroup(); mode |= ReUI().onRaceEventFinished(nbTrk != 1, careerNonHumanGroup) ? RM_SYNC : RM_ASYNC;; if (mode & RM_NEXT_STEP) FREEZ(ReInfo->_reCarInfo); return mode; }
void ReUpdateStandings(void) { tReStandings st; std::string drvName; std::vector<tReStandings> *standings; std::vector<tReStandings>::iterator found; std::vector<tReStandings>::iterator it; int runDrv, curDrv; int i; void *results = ReInfo->results; snprintf(path, sizeof(path), "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK); runDrv = GfParmGetEltNb(results, path); curDrv = GfParmGetEltNb(results, RE_SECT_STANDINGS); standings = new std::vector<tReStandings>; standings->reserve(curDrv); /* Read the current standings */ for (i = 0; i < curDrv; i++) { snprintf(path2, sizeof(path2), "%s/%d", RE_SECT_STANDINGS, i + 1); st.drvName = GfParmGetStr(results, path2, RE_ATTR_NAME, 0); st.modName = GfParmGetStr(results, path2, RE_ATTR_MODULE, 0); st.carName = GfParmGetStr(results, path2, RE_ATTR_CAR, 0); st.extended = (int)GfParmGetNum(results, path2, RM_ATTR_EXTENDED, NULL, 0); st.drvIdx = (int)GfParmGetNum(results, path2, RE_ATTR_IDX, NULL, 0); st.points = (int)GfParmGetNum(results, path2, RE_ATTR_POINTS, NULL, 0); standings->push_back(st); }//for i //Void the stored results GfParmListClean(results, RE_SECT_STANDINGS); //Check last races' drivers and search their name in the results. //If found there, adds recent points. //If not found, adds the driver for (i = 0; i < runDrv; i++) { //Search the driver name in the standings snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK, i + 1); drvName = GfParmGetStr(results, path, RE_ATTR_NAME, 0); found = std::find(standings->begin(), standings->end(), drvName); if(found == standings->end()) { //No such driver in the standings, let's add it st.drvName = drvName; st.modName = GfParmGetStr(results, path, RE_ATTR_MODULE, 0); st.carName = GfParmGetStr(results, path, RE_ATTR_CAR, 0); st.extended = (int)GfParmGetNum(results, path, RM_ATTR_EXTENDED, NULL, 0); st.drvIdx = (int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0); st.points = (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0); standings->push_back(st); } else { //Driver found, add recent points found->points += (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0); }//if found }//for i //sort standings by score std::sort(standings->begin(), standings->end(), sortByScore); //Store the standing back for(it = standings->begin(), i = 0; it != standings->end(); ++it, ++i) { snprintf(path, sizeof(path), "%s/%d", RE_SECT_STANDINGS, i + 1); GfParmSetStr(results, path, RE_ATTR_NAME, it->drvName.c_str()); GfParmSetStr(results, path, RE_ATTR_MODULE, it->modName.c_str()); GfParmSetStr(results, path, RE_ATTR_CAR, it->carName.c_str()); GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)it->drvIdx); GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, (tdble)it->points); }//for it delete standings; char str1[512], str2[512]; snprintf(str1, sizeof(str1), "%sconfig/params.dtd", GfDataDir()); snprintf(str2, sizeof(str2), "<?xml-stylesheet type=\"text/xsl\" href=\"file:///%sconfig/raceresults.xsl\"?>", GfDataDir()); GfParmSetDTD (results, str1, str2); GfParmWriteFile(0, results, "Results"); }//ReUpdateStandings
/** * Function to load a car. * * @param carindex The index whichs will be used as car->index for the car. * @param listindex The listindex in RM_SECT_DRIVERS_RACING * @param modindex The index of the mod; must be MAX_MOD_ITF if normal_carname is FALSE. * @param robotIdx The index of the robot. * @param normal_carname If this member is TRUE, the car is treated as an ordinary car; * if this member is FALSE, then the car used is the one given * in the xml-file, and there is no restriction on the number of instances. * @param cardllname The dllname of the driver * @return A pointer to the newly created car if successfull; NULL otherwise */ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int relativeRobotIdx, char normal_carname, char const *cardllname ) { tCarElt *elt; tMemoryPool oldPool; char path[256]; char path2[256]; char buf[256]; char buf2[256]; char const *str; char const *category; char const *subcategory; char const *teamname; std::string carname; tModInfoNC *curModInfo; tRobotItf *curRobot; void *robhdle; void *cathdle; void *carhdle; void *handle; int k; int xx; char isHuman; int robotIdx = relativeRobotIdx; /* good robot found */ curModInfo = &((*(ReInfo->robModList))->modInfo[modindex]); subcategory = ReInfo->track->subcategory; #if 0 //SDW if (replayReplay) GfLogInfo("Driver in car %d being driven by replay\n", carindex); else #endif GfLogInfo("Driver's name: %s\n", curModInfo->name); isHuman = strcmp( cardllname, "human" ) == 0 || strcmp( cardllname, "networkhuman" ) == 0; /* Extended is forced for humans, so no need to increase robotIdx */ if (!normal_carname && !isHuman) robotIdx += curModInfo->index; /* Retrieve the driver interface (function pointers) */ curRobot = (tRobotItf*)calloc(1, sizeof(tRobotItf)); /* ... and initialize the driver */ #if 0 // SDW if (replayReplay) { // Register against the Replay driver (which does nothing) curModInfo->fctInit(carindex, (void*)(curRobot)); } else if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { #else if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { #endif curModInfo->fctInit(robotIdx, (void*)(curRobot)); } else { curRobot->rbNewTrack = NULL; curRobot->rbNewRace = NULL; curRobot->rbResumeRace = NULL; curRobot->rbDrive = NULL; curRobot->rbPitCmd = NULL; curRobot->rbEndRace = NULL; curRobot->rbShutdown = NULL; curRobot->index = 0; } /* Retrieve and load the robotXML file : 1) from user settings dir (local dir) 2) from installed data dir */ snprintf(buf, sizeof(buf), "%sdrivers/%s/%s.xml", GfLocalDir(), cardllname, cardllname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { snprintf(buf, sizeof(buf), "drivers/%s/%s.xml", cardllname, cardllname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } if (normal_carname || isHuman) snprintf(path, sizeof(path), "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx); else snprintf(path, sizeof(path), "%s", ROB_SECT_ARBITRARY); /* Load car/driver info (in race engine data structure) */ if (robhdle) { elt = &(ReInfo->carList[carindex]); GF_TAILQ_INIT(&(elt->_penaltyList)); const std::string strDType = GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT); if (strDType == ROB_VAL_ROBOT){ elt->_driverType = RM_DRV_ROBOT; elt->_networkPlayer = 0; } else if (strDType == ROB_VAL_HUMAN) { elt->_driverType = RM_DRV_HUMAN; std::string strNetPlayer = GfParmGetStr(robhdle, path, "networkrace", "no"); elt->_networkPlayer = (strNetPlayer == "yes") ? 1 : 0; } elt->index = carindex; elt->robot = curRobot; elt->_paramsHandle = robhdle; elt->_driverIndex = robotIdx; elt->_moduleIndex = relativeRobotIdx; strncpy(elt->_modName, cardllname, MAX_NAME_LEN - 1); elt->_modName[MAX_NAME_LEN - 1] = 0; //snprintf(path, sizeof(path), "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx); snprintf( path2, sizeof(path2), "%s/%s/%d/%d", RM_SECT_DRIVERINFO, elt->_modName, normal_carname ? 0 : 1, elt->_moduleIndex ); if (normal_carname || elt->_driverType == RM_DRV_HUMAN) { strncpy(elt->_name, GfParmGetStr(robhdle, path, ROB_ATTR_NAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_sname, GfParmGetStr(robhdle, path, ROB_ATTR_SNAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_cname, GfParmGetStr(robhdle, path, ROB_ATTR_CODE, "---"), 3); } else { strncpy(elt->_name, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_NAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_sname, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_SNAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_cname, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_CODE, "---"), 3); } elt->_name[MAX_NAME_LEN - 1] = 0; elt->_sname[MAX_NAME_LEN - 1] = 0; elt->_cname[3] = 0; teamname = GfParmGetStr(robhdle, path, ROB_ATTR_TEAM, "none"); teamname = GfParmGetStr(ReInfo->params, path2, ROB_ATTR_TEAM, teamname ); //Use the name in params if it has a team name strncpy(elt->_teamname, teamname, MAX_NAME_LEN - 1); elt->_teamname[MAX_NAME_LEN - 1] = 0; elt->_driveSkill = GfParmGetNum(ReInfo->params, path2, RM_ATTR_SKILLLEVEL, NULL, -1.0f); if (normal_carname) /* Even if we get a normal_carname for humans we use it despite of forced extended mode*/ strncpy(elt->_carName, GfParmGetStr(robhdle, path, ROB_ATTR_CAR, ""), MAX_NAME_LEN - 1); else strncpy(elt->_carName, GfParmGetStr(ReInfo->params, path2, RM_ATTR_CARNAME, ""), MAX_NAME_LEN - 1); elt->_carName[MAX_NAME_LEN - 1] = 0; /* XML file name */ // Load custom skin name and targets from race info (if specified). snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, listindex); if (GfParmGetStr(ReInfo->params, path2, RM_ATTR_SKINNAME, 0)) { strncpy(elt->_skinName, GfParmGetStr(ReInfo->params, path2, RM_ATTR_SKINNAME, ""), MAX_NAME_LEN - 1); elt->_skinName[MAX_NAME_LEN - 1] = 0; // Texture name } elt->_skinTargets = (int)GfParmGetNum(ReInfo->params, path2, RM_ATTR_SKINTARGETS, (char*)NULL, 0); // Load other data from robot descriptor. elt->_raceNumber = (int)GfParmGetNum(robhdle, path, ROB_ATTR_RACENUM, (char*)NULL, 0); if (!normal_carname && elt->_driverType != RM_DRV_HUMAN) // Increase racenumber if needed elt->_raceNumber += elt->_moduleIndex; elt->_skillLevel = 0; str = GfParmGetStr(robhdle, path, ROB_ATTR_LEVEL, ROB_VAL_SEMI_PRO); for(k = 0; k < NSkillLevels; k++) { if (strcmp(aPszSkillLevelNames[k], str) == 0) { elt->_skillLevel = k; break; } } elt->_startRank = carindex; elt->_pos = carindex+1; elt->_remainingLaps = ReInfo->s->_totLaps; elt->_newTrackMemPool = NULL; elt->_newRaceMemPool = NULL; elt->_endRaceMemPool = NULL; elt->_shutdownMemPool = NULL; carname = elt->_carName; GfLogTrace("Driver #%d(%d) : module='%s', name='%s', car='%s', cat='%s', skin='%s' on %x\n", carindex, listindex, elt->_modName, elt->_name, elt->_carName, elt->_category, elt->_skinName, elt->_skinTargets); if ((strncmp(carname.c_str(), "mpa1", 4) == 0)) { if (strcmp(subcategory, "long") == 0) carname = carname+"-long"; else if (strcmp(subcategory, "short") == 0) carname = carname+"-short"; else carname = carname+"-road"; GfLogTrace("MPA... Category car = %s \n", carname.c_str()); /* Retrieve and load car specs : merge car default specs, category specs and driver modifications (=> handle) */ /* Read Car model specifications */ snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, carname.c_str()); carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); } else { /* Retrieve and load car specs : merge car default specs, category specs and driver modifications (=> handle) */ /* Read Car model specifications */ snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, elt->_carName); carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); } category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL); if (category) { GfLogTrace("Checking/Merging %s specs into %s base setup for %s ...\n", category, elt->_carName, curModInfo->name); strncpy(elt->_category, category, MAX_NAME_LEN - 1); elt->_category[MAX_NAME_LEN - 1] = 0; /* Read Car Category specifications */ snprintf(buf2, sizeof(buf2), "cars/categories/%s.xml", elt->_category); cathdle = GfParmReadFile(buf2, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); int errorcode = 0; if ((errorcode = GfParmCheckHandle(cathdle, carhdle))) { switch (errorcode) { case -1: GfLogError("Car %s NOT in category %s (driver %s) !!!\n", elt->_carName, category, elt->_name); break; case -2: GfLogError("Parameters out of bound for car %s (driver %s)!!!\n",elt->_carName, elt->_name); break; case -3: GfLogError("Parameter not allowed for car %s (driver %s)!!!\n",elt->_carName, elt->_name); break; default: GfLogError("Unknown error for %s (driver %s)!!!\n",elt->_carName, elt->_name); break; } return NULL; } carhdle = GfParmMergeHandles(cathdle, carhdle, GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST); /* The code below stores the carnames to a separate xml-file such that at newTrack it is known which car is used. TODO: find a better method for this */ snprintf (buf, sizeof(buf), "%sdrivers/curcarnames.xml", GfLocalDir()); handle = GfParmReadFile(buf, GFPARM_RMODE_CREAT); if (handle) { snprintf(path, sizeof(path), "drivers/%s/%d", cardllname, elt->_driverIndex); GfParmSetStr (handle, path, RM_ATTR_CARNAME, elt->_carName); GfParmWriteFile (0, handle, "Car names"); GfParmReleaseHandle (handle); } if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { GfPoolMove(&elt->_newTrackMemPool, &oldPool); curRobot->rbNewTrack(elt->_driverIndex, ReInfo->track, carhdle, &handle, ReInfo->s); GfPoolFreePool( &oldPool ); } else handle = NULL; if (handle && !replayReplay) { GfLogTrace("Checking/Merging %s specific setup into %s setup.\n", curModInfo->name, elt->_carName); if (GfParmCheckHandle(carhdle, handle)) { GfLogError("Bad Car parameters for driver %s\n", elt->_name); return NULL; } handle = GfParmMergeHandles(carhdle, handle, GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST); } else { GfLogTrace("Keeping %s setup as is for %s (no specific setup).\n", elt->_carName, curModInfo->name); handle = carhdle; } elt->_carHandle = handle; /* Initialize sectors */ elt->_currentSector = 0; elt->_curSplitTime = (double*)malloc( sizeof(double) * ( ReInfo->track->numberOfSectors - 1 ) ); elt->_bestSplitTime = (double*)malloc( sizeof(double) * ( ReInfo->track->numberOfSectors - 1 ) ); for (xx = 0; xx < ReInfo->track->numberOfSectors - 1; ++xx) { elt->_curSplitTime[xx] = -1.0f; elt->_bestSplitTime[xx] = -1.0f; } } else { elt->_category[ 0 ] = '\0'; GfLogError("Bad Car category for driver %s\n", elt->_name); return NULL; } return elt; } else { GfLogError("No description file for robot %s\n", cardllname); } return NULL; } /** Initialize the cars for a race. The cars are positionned on the starting grid. @return 0 Ok, -1 Error */ int ReInitCars(void) { char buf[512]; char path[512]; int nCars; int index; int i, j; const char *robotModuleName; int robotIdx; void *robhdle; tCarElt *elt; //const char *focused; // Never used. //int focusedIdx; // Never used. void *params = ReInfo->params; /* Get the number of cars (= drivers) racing */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS_RACING); GfLogTrace("Loading %d car(s)\n", nCars); FREEZ(ReInfo->carList); ReInfo->carList = (tCarElt*)calloc(nCars, sizeof(tCarElt)); FREEZ(ReInfo->rules); ReInfo->rules = (tRmCarRules*)calloc(nCars, sizeof(tRmCarRules)); //focused = GfParmGetStr(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); //focusedIdx = (int)GfParmGetNum(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL, 0); index = 0; /* For each car/driver : */ for (i = 1; i < nCars + 1; i++) { /* Get the name of the module (= shared library) of the robot */ snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS_RACING, i); robotModuleName = GfParmGetStr(ReInfo->params, path, RM_ATTR_MODULE, ""); robotIdx = (int)GfParmGetNum(ReInfo->params, path, RM_ATTR_IDX, NULL, 0); #if 0 // SDW if (replayReplay) // Register against the Replay driver snprintf(path, sizeof(path), "%sdrivers/replay/replay.%s", GfLibDir(), DLLEXT); else #endif snprintf(path, sizeof(path), "%sdrivers/%s/%s.%s", GfLibDir(), robotModuleName, robotModuleName, DLLEXT); /* Load the robot shared library */ if (GfModLoad(CAR_IDENT, path, ReInfo->robModList)) { GfLogError("Failed to load robot module %s\n", path); continue; } /* Load the racing driver info in the race data structure */ elt = NULL; snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS_RACING, i); if ((int)GfParmGetNum(ReInfo->params, path, RM_ATTR_EXTENDED, NULL, 0) == 0) { /* Search for the index of the racing driver in the list of interfaces of the module */ for (j = 0; j < (*(ReInfo->robModList))->modInfoSize; j++) { if ((*(ReInfo->robModList))->modInfo[j].name && (*(ReInfo->robModList))->modInfo[j].index == robotIdx) { /* We have the right driver : load it */ elt = reLoadSingleCar( index, i, j, robotIdx, TRUE, robotModuleName ); if (!elt) { GfLogError("No descriptor file for robot %s or parameter errors (1)\n", robotModuleName); snprintf(buf, sizeof(buf), "Error: May be no driver, or some parameters are out of bound"); ReUI().addLoadingMessage(buf); snprintf(buf, sizeof(buf), " Have a look at the console window for mode details about the error"); ReUI().addLoadingMessage(buf); snprintf(buf, sizeof(buf), " Back to the config menu in 10 s ..."); ReUI().addLoadingMessage(buf); // Wait some time to allow the user to read the message! GfSleep(10.0); // 10 seconds } } } } else { GfLogTrace("Loading robot %s descriptor file\n", robotModuleName ); snprintf(buf, sizeof(buf), "%sdrivers/%s/%s.xml", GfLocalDir(), robotModuleName, robotModuleName); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { snprintf(buf, sizeof(buf), "drivers/%s/%s.xml", robotModuleName, robotModuleName); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } if (robhdle && ( strcmp( robotModuleName, "human" ) == 0 || strcmp( robotModuleName, "networkhuman" ) == 0 ) ) { /* Human driver */ elt = reLoadSingleCar( index, i, robotIdx - (*(ReInfo->robModList))->modInfo[0].index, robotIdx, FALSE, robotModuleName ); } else if (robhdle && ( strcmp( GfParmGetStr( robhdle, ROB_SECT_ARBITRARY, ROB_ATTR_TEAM, "foo" ), GfParmGetStr( robhdle, ROB_SECT_ARBITRARY, ROB_ATTR_TEAM, "bar" ) ) == 0 ) ) { elt = reLoadSingleCar( index, i, (*(ReInfo->robModList))->modInfoSize, robotIdx, FALSE, robotModuleName ); } else GfLogError("No descriptor for robot %s (2)\n", robotModuleName ); } if (elt) ++index; } nCars = index; /* real number of cars */ if (nCars == 0) { GfLogError("No driver for that race ; exiting ...\n"); return -1; } else { GfLogInfo("%d driver(s) ready to race\n", nCars); } if (replayReplay) replayRecord = 0; else { char buf[1024]; const char *replayRateSchemeName; snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, "0"); GfParmReleaseHandle(paramHandle); replayRecord = atoi(replayRateSchemeName); } if (replayRecord || replayReplay) { #ifdef THIRD_PARTY_SQLITE3 int result; result = sqlite3_open("/tmp/race.sqlite", &replayDB); if (result) { GfLogError("Replay: Unable to open Database: %s\n", sqlite3_errmsg(replayDB)); sqlite3_close(replayDB); replayDB = NULL; } else { GfLogInfo("Replay: Database Opened 0x8%8.8X\n", replayDB); if (replayRecord) GfLogInfo("Replay: Record Timestep = %f\n", 1/(float)replayRecord); if (replayReplay) GfLogInfo("Replay: Playback from file\n"); /* speed up database by turning of synchronous behaviour/etc */ sqlite3_exec(replayDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL); sqlite3_exec(replayDB, "PRAGMA journal_mode = OFF", NULL, NULL, NULL); sqlite3_exec(replayDB, "PRAGMA count_changes = OFF", NULL, NULL, NULL); #if 0 // This pragma seems to prevent re-opening the sqlite3 database sqlite3_exec(replayDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL, NULL); #endif sqlite3_exec(replayDB, "PRAGMA default_temp_store = MEMORY", NULL, NULL, NULL); //replayBlobs = (sqlite3_stmt *) calloc(nCars, sizeof(void *)); //sqlite3_stmt)); replayTimestamp = -5; ghostcarActive = 0; } #endif } ReInfo->s->_ncars = nCars; FREEZ(ReInfo->s->cars); ReInfo->s->cars = (tCarElt **)calloc(nCars, sizeof(tCarElt *)); for (i = 0; i < nCars; i++) { ReInfo->s->cars[i] = &(ReInfo->carList[i]); #ifdef THIRD_PARTY_SQLITE3 //open a table for each car if (replayDB) { char command[200]; int result; if (replayRecord) { sprintf(command, "DROP TABLE IF EXISTS car%d", i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) GfLogInfo("Replay: Unable to drop table car%d: %s\n", i, sqlite3_errmsg(replayDB)); } sprintf(command, "CREATE TABLE IF NOT EXISTS car%d (timestamp, lap, datablob BLOB)", i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) { GfLogInfo("Replay: Unable to create table car%d: %s\n", i, sqlite3_errmsg(replayDB)); exit(0); } if (replayReplay) { // Build index to allow faster read access sprintf(command, "CREATE UNIQUE INDEX IF NOT EXISTS index%d ON car%d (timestamp)", i, i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) GfLogInfo("Replay: Unable to create index car%d: %s\n", i, sqlite3_errmsg(replayDB)); } } #endif } ReInfo->_rePitRequester = 0; // TODO: reconsider splitting the call into one for cars, track and maybe other objects. // I stuff for now anything into one call because collision detection works with the same // library on all objects, so it is a bit dangerous to distribute the handling to various // locations (because the library maintains global state like a default collision handler etc.). RePhysicsEngine().initialize(nCars, ReInfo->track); initStartingGrid(); initPits(); return 0; }
void ReStoreRaceResults(const char *race) { int i; int nCars; tCarElt *car; tSituation *s = ReInfo->s; char *carName; void *carparam; void *results = ReInfo->results; void *params = ReInfo->params; /* Store the number of laps of the race */ switch (ReInfo->s->_raceType) { case RM_TYPE_RACE: car = s->cars[0]; if (car->_laps > s->_totLaps) car->_laps = s->_totLaps + 1; snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race); GfParmListClean(results, path); GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, (tdble)(car->_laps - 1)); for (i = 0; i < s->_ncars; i++) { snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); car = s->cars[i]; if (car->_laps > s->_totLaps) car->_laps = s->_totLaps + 1; GfParmSetStr(results, path, RE_ATTR_NAME, car->_name); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carName = GfParmGetName(carparam); GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, (tdble)car->index); GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, (tdble)(car->_laps - 1)); GfParmSetNum(results, path, RE_ATTR_TIME, NULL, (tdble)car->_curTime); GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, (tdble)car->_bestLapTime); GfParmSetNum(results, path, RE_ATTR_TOP_SPEED, NULL, car->_topSpeed); GfParmSetNum(results, path, RE_ATTR_DAMMAGES, NULL, (tdble)car->_dammage); GfParmSetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, (tdble)car->_nbPitStops); GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName); GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)car->_moduleIndex); snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, car->index + 1 ); GfParmSetNum(results, path, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path2, RM_ATTR_EXTENDED, NULL, 0)); GfParmSetStr(results, path, ROB_ATTR_CAR, car->_carName); snprintf(path2, sizeof(path2), "%s/%s/%d", race, RM_SECT_POINTS, i + 1); GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0)); if (strlen(car->_skinName) > 0) GfParmSetStr(results, path, RM_ATTR_SKINNAME, car->_skinName); GfParmSetNum(results, path, RM_ATTR_SKINTARGETS, NULL, (tdble)car->_skinTargets); GfParmReleaseHandle(carparam); } break; case RM_TYPE_PRACTICE: if (s->_ncars == 1) { car = s->cars[0]; snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race); GfParmSetStr(results, path, RM_ATTR_DRVNAME, car->_name); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carName = GfParmGetName(carparam); GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmReleaseHandle(carparam); break; } /* Otherwise, fall through */ case RM_TYPE_QUALIF: if (s->_ncars == 1) { car = s->cars[0]; snprintf(path, sizeof(path), "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK); nCars = GfParmGetEltNb(results, path); for (i = nCars; i > 0; i--) { snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i); float opponentBestLapTime = GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0); if (car->_bestLapTime != 0.0 && (car->_bestLapTime < opponentBestLapTime || opponentBestLapTime == 0.0)) { /* shift */ snprintf(path2, sizeof(path2), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); GfParmSetStr(results, path2, RE_ATTR_NAME, GfParmGetStr(results, path, RE_ATTR_NAME, "")); GfParmSetStr(results, path2, RE_ATTR_CAR, GfParmGetStr(results, path, RE_ATTR_CAR, "")); GfParmSetNum(results, path2, RE_ATTR_BEST_LAP_TIME, NULL, GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0)); GfParmSetStr(results, path2, RE_ATTR_MODULE, GfParmGetStr(results, path, RM_ATTR_MODULE, "")); GfParmSetNum(results, path2, RE_ATTR_IDX, NULL, GfParmGetNum(results, path, RM_ATTR_IDX, NULL, 0)); GfParmSetNum(results, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(results, path, RM_ATTR_EXTENDED, NULL, 0)); GfParmSetStr(results, path2, ROB_ATTR_CAR, GfParmGetStr(results, path, ROB_ATTR_CAR, "")); GfParmSetStr(results, path2, ROB_ATTR_NAME, GfParmGetStr(results, path, ROB_ATTR_NAME, "")); snprintf(path, sizeof(path), "%s/%s/%d", race, RM_SECT_POINTS, i + 1); GfParmSetNum(results, path2, RE_ATTR_POINTS, NULL, GfParmGetNum(params, path, RE_ATTR_POINTS, NULL, 0)); if (GfParmGetStr(results, path, RM_ATTR_SKINNAME, 0)) GfParmSetStr(results, path2, RM_ATTR_SKINNAME, GfParmGetStr(results, path, RM_ATTR_SKINNAME, 0)); GfParmSetNum(results, path2, RM_ATTR_SKINTARGETS, NULL, GfParmGetNum(results, path, RM_ATTR_SKINTARGETS, NULL, 0)); } else { break; } } /* insert after */ snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); GfParmSetStr(results, path, RE_ATTR_NAME, car->_name); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carName = GfParmGetName(carparam); GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, (tdble)car->_bestLapTime); GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName); GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)car->_moduleIndex); GfParmSetStr(results, path, ROB_ATTR_CAR, car->_carName); GfParmSetStr(results, path, ROB_ATTR_NAME, car->_name); snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, car->index + 1 ); GfParmSetNum(results, path, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path2, RM_ATTR_EXTENDED, NULL, 0)); snprintf(path2, sizeof(path2), "%s/%s/%d", race, RM_SECT_POINTS, i + 1); GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0)); if (strlen(car->_skinName) > 0) GfParmSetStr(results, path, RM_ATTR_SKINNAME, car->_skinName); GfParmSetNum(results, path, RM_ATTR_SKINTARGETS, NULL, (tdble)car->_skinTargets); GfParmReleaseHandle(carparam); break; } else { car = s->cars[0]; if (s->_totTime < 0.0f) GfLogWarning("Saving results of multicar non-race session, but it was not timed!\n" ); snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race); GfParmListClean(results, path); GfParmSetNum(results, path, RE_ATTR_SESSIONTIME, NULL, (tdble)s->_totTime); for (i = 0; i < s->_ncars; i++) { snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); car = s->cars[i]; GfParmSetStr(results, path, RE_ATTR_NAME, car->_name); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carName = GfParmGetName(carparam); GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, (tdble)car->index); GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, (tdble)(car->_laps - 1)); GfParmSetNum(results, path, RE_ATTR_TIME, NULL, (tdble)car->_curTime); GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, (tdble)car->_bestLapTime); GfParmSetNum(results, path, RE_ATTR_TOP_SPEED, NULL, car->_topSpeed); GfParmSetNum(results, path, RE_ATTR_DAMMAGES, NULL, (tdble)car->_dammage); GfParmSetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, (tdble)car->_nbPitStops); GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName); GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)car->_moduleIndex); snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, car->index + 1 ); GfParmSetNum(results, path, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path2, RM_ATTR_EXTENDED, NULL, 0)); GfParmSetStr(results, path, ROB_ATTR_CAR, car->_carName); snprintf(path2, sizeof(path2), "%s/%s/%d", race, RM_SECT_POINTS, i + 1); GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0)); if (strlen(car->_skinName) > 0) GfParmSetStr(results, path, RM_ATTR_SKINNAME, car->_skinName); GfParmSetNum(results, path, RM_ATTR_SKINTARGETS, NULL, (tdble)car->_skinTargets); GfParmReleaseHandle(carparam); } break; } } }
static void rmSelectDeselect(void * /* dummy */ ) { char *name; int src, dst; tDrvElt *curDrv; char *cardllname; int robotIdx; int sel; sel = 0; name = 0; if (nbSelectedDrivers < nbMaxSelectedDrivers) { src = unselectedScrollList; name = GfuiScrollListExtractSelectedElement(scrHandle, src, (void**)&curDrv); if (name) { dst = selectedScrollList; GfuiScrollListInsertElement(scrHandle, dst, name, 100, (void*)curDrv); nbSelectedDrivers++; } } if (!name) { sel = 1; src = selectedScrollList; name = GfuiScrollListExtractSelectedElement(scrHandle, src, (void**)&curDrv); if (name) { dst = unselectedScrollList; if (curDrv->human) { GfuiScrollListInsertElement(scrHandle, dst, name, 0, (void*)curDrv); } else { GfuiScrollListInsertElement(scrHandle, dst, name, 100, (void*)curDrv); } nbSelectedDrivers--; } else { return; } } cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0); if (sel) { cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0); if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) { /* the focused element was deselected select a new one */ name = GfuiScrollListGetElement(scrHandle, selectedScrollList, 0, (void**)&curDrv); if (name) { GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, curDrv->dname); GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, curDrv->index); GfuiLabelSetText(scrHandle, FocDrvLabelId, curDrv->name); } else { GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0); GfuiLabelSetText(scrHandle, FocDrvLabelId, ""); } } } else { if ((strlen(cardllname) == 0) || (curDrv->human)) { GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, curDrv->dname); GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, curDrv->index); GfuiLabelSetText(scrHandle, FocDrvLabelId, curDrv->name); } } rmdsClickOnDriver(NULL); }
void ReUpdateStandings(void) { int maxDrv; int curDrv; int runDrv; char *modName; int drvIdx; int points; int i, j; int found; tReStandings *standings = 0; void *results = ReInfo->results; const int BUFSIZE = 1024; char str1[BUFSIZE], str2[BUFSIZE], path[BUFSIZE], path2[BUFSIZE]; snprintf(path, BUFSIZE, "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK); runDrv = GfParmGetEltNb(results, path); curDrv = GfParmGetEltNb(results, RE_SECT_STANDINGS); maxDrv = curDrv + runDrv; standings = (tReStandings *)calloc(maxDrv, sizeof(tReStandings)); /* Read the current standings */ for (i = 0; i < curDrv; i++) { snprintf(path2, BUFSIZE, "%s/%d", RE_SECT_STANDINGS, i + 1); standings[i].carName = strdup(GfParmGetStr(results, path2, RE_ATTR_NAME, 0)); standings[i].modName = strdup(GfParmGetStr(results, path2, RE_ATTR_MODULE, 0)); standings[i].drvIdx = (int)GfParmGetNum(results, path2, RE_ATTR_IDX, NULL, 0); standings[i].points = (int)GfParmGetNum(results, path2, RE_ATTR_POINTS, NULL, 0); } GfParmListClean(results, RE_SECT_STANDINGS); for (i = 0; i < runDrv; i++) { /* Search the driver in the standings */ found = 0; snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK, i + 1); const char* carName = GfParmGetStr(results, path, RE_ATTR_NAME, 0); for (j = 0; j < curDrv; j++) { if (!strcmp(carName, standings[j].carName)) { found = 1; break; } } if (!found) { /* Add the new driver */ curDrv++; standings[j].carName = strdup(carName); standings[j].modName = strdup(GfParmGetStr(results, path, RE_ATTR_MODULE, 0)); standings[j].drvIdx = (int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0); standings[j].points = (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0); } else { /* Add the new points */ standings[j].points += (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0); } /* bubble sort... */ while (j > 0) { if (standings[j - 1].points >= standings[j].points) { break; } /* Swap with preceeding */ carName = standings[j].carName; modName = standings[j].modName; drvIdx = standings[j].drvIdx; points = standings[j].points; standings[j].carName = standings[j - 1].carName; standings[j].modName = standings[j - 1].modName; standings[j].drvIdx = standings[j - 1].drvIdx; standings[j].points = standings[j - 1].points; standings[j - 1].carName = carName; standings[j - 1].modName = modName; standings[j - 1].drvIdx = drvIdx; standings[j - 1].points = points; j--; } } /* Store the standing back */ for (i = 0; i < curDrv; i++) { snprintf(path, BUFSIZE, "%s/%d", RE_SECT_STANDINGS, i + 1); GfParmSetStr(results, path, RE_ATTR_NAME, standings[i].carName); //free(standings[i].carName); GfParmSetStr(results, path, RE_ATTR_MODULE, standings[i].modName); free(standings[i].modName); GfParmSetNum(results, path, RE_ATTR_IDX, NULL, standings[i].drvIdx); GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, standings[i].points); } free(standings); snprintf(str1, BUFSIZE, "%sconfig/params.dtd", GetDataDir()); snprintf(str2, BUFSIZE, "<?xml-stylesheet type=\"text/xsl\" href=\"file:///%sconfig/style.xsl\"?>", GetDataDir()); GfParmSetDTD (results, str1, str2); GfParmWriteFile(0, results, "Results"); }
/* return state mode */ int ReRaceStart(void) { int i; int nCars; int maxCars; const char *raceName = ReInfo->_reRaceName; void *params = ReInfo->params; void *results = ReInfo->results; const int BUFSIZE = 1024; char path[BUFSIZE], path2[BUFSIZE]; FREEZ(ReInfo->_reCarInfo); ReInfo->_reCarInfo = (tReCarInfo*)calloc(GfParmGetEltNb(params, RM_SECT_DRIVERS), sizeof(tReCarInfo)); /* Drivers starting order */ GfParmListClean(params, RM_SECT_DRIVERS_RACING); if (ReInfo->s->_raceType == RM_TYPE_QUALIF) { i = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1); if (i == 1) { RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png"); RmLoadingScreenSetText("Preparing Starting Grid..."); } else { RmShutdownLoadingScreen(); } snprintf(path, BUFSIZE, "%s/%d", RM_SECT_DRIVERS, i); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, 1); GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RM_ATTR_MODULE, "")); GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0)); } else { RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png"); RmLoadingScreenSetText("Preparing Starting Grid..."); const char* gridType = GfParmGetStr(params, raceName, RM_ATTR_START_ORDER, RM_VAL_DRV_LIST_ORDER); if (!strcmp(gridType, RM_VAL_LAST_RACE_ORDER)) { /* Starting grid in the arrival of the previous race */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); const char* prevRaceName = ReGetPrevRaceName(); if (!prevRaceName) { return RM_QUIT; } for (i = 1; i < nCars + 1; i++) { snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, i); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i); GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(results, path, RE_ATTR_MODULE, "")); GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0)); } } else if (!strcmp(gridType, RM_VAL_LAST_RACE_RORDER)) { /* Starting grid in the reversed arrival order of the previous race */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); const char* prevRaceName = ReGetPrevRaceName(); if (!prevRaceName) { return RM_QUIT; } for (i = 1; i < nCars + 1; i++) { snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, nCars - i + 1); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i); GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(results, path, RE_ATTR_MODULE, "")); GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0)); } } else { /* Starting grid in the drivers list order */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); for (i = 1; i < nCars + 1; i++) { snprintf(path, BUFSIZE, "%s/%d", RM_SECT_DRIVERS, i); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i); GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RM_ATTR_MODULE, "")); GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0)); } } } if (ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) { if (!strcmp(GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_SPLASH_MENU, RM_VAL_NO), RM_VAL_YES)) { RmShutdownLoadingScreen(); RmDisplayStartRace(ReInfo, StartRaceHookInit(), AbandonRaceHookInit()); return RM_ASYNC | RM_NEXT_STEP; } } return reRaceRealStart(); }
void ReStoreRaceResults(const char *race) { int i; int nCars; tCarElt *car; tSituation *s = ReInfo->s; char *carName; void *carparam; void *results = ReInfo->results; void *params = ReInfo->params; const int BUFSIZE = 1024; char buf[BUFSIZE], path[BUFSIZE], path2[BUFSIZE]; /* Store the number of laps of the race */ switch (ReInfo->s->_raceType) { case RM_TYPE_RACE: car = s->cars[0]; if (car->_laps > s->_totLaps) car->_laps = s->_totLaps + 1; snprintf(path, BUFSIZE, "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race); GfParmListClean(results, path); GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, car->_laps - 1); for (i = 0; i < s->_ncars; i++) { snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); car = s->cars[i]; if (car->_laps > s->_totLaps) car->_laps = s->_totLaps + 1; GfParmSetStr(results, path, RE_ATTR_NAME, car->_name); snprintf(buf, BUFSIZE, "cars/%s/%s.xml", car->_carName, car->_carName); carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carName = GfParmGetName(carparam); GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, car->index); GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, car->_laps - 1); GfParmSetNum(results, path, RE_ATTR_TIME, NULL, car->_curTime); GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, car->_bestLapTime); GfParmSetNum(results, path, RE_ATTR_TOP_SPEED, NULL, car->_topSpeed); GfParmSetNum(results, path, RE_ATTR_DAMMAGES, NULL, car->_dammage); GfParmSetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, car->_nbPitStops); GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName); GfParmSetNum(results, path, RE_ATTR_IDX, NULL, car->_driverIndex); snprintf(path2, BUFSIZE, "%s/%s/%d", race, RM_SECT_POINTS, i + 1); GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, (int)GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0)); GfParmReleaseHandle(carparam); } break; case RM_TYPE_PRACTICE: car = s->cars[0]; snprintf(path, BUFSIZE, "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race); GfParmSetStr(results, path, RM_ATTR_DRVNAME, car->_name); break; case RM_TYPE_QUALIF: car = s->cars[0]; snprintf(path, BUFSIZE, "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK); nCars = GfParmGetEltNb(results, path); for (i = nCars; i > 0; i--) { snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i); float opponentBestLapTime = GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0); if ( (car->_bestLapTime != 0.0) && ((car->_bestLapTime < opponentBestLapTime) || (opponentBestLapTime == 0.0)) ) { /* shift */ snprintf(path2, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); GfParmSetStr(results, path2, RE_ATTR_NAME, GfParmGetStr(results, path, RE_ATTR_NAME, "")); GfParmSetStr(results, path2, RE_ATTR_CAR, GfParmGetStr(results, path, RE_ATTR_CAR, "")); GfParmSetNum(results, path2, RE_ATTR_BEST_LAP_TIME, NULL, GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0)); GfParmSetStr(results, path2, RE_ATTR_MODULE, GfParmGetStr(results, path, RM_ATTR_MODULE, "")); GfParmSetNum(results, path2, RE_ATTR_IDX, NULL, GfParmGetNum(results, path, RM_ATTR_IDX, NULL, 0)); snprintf(path, BUFSIZE, "%s/%s/%d", race, RM_SECT_POINTS, i + 1); GfParmSetNum(results, path2, RE_ATTR_POINTS, NULL, (int)GfParmGetNum(params, path, RE_ATTR_POINTS, NULL, 0)); } else { break; } } /* insert after */ snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); GfParmSetStr(results, path, RE_ATTR_NAME, car->_name); snprintf(buf, BUFSIZE, "cars/%s/%s.xml", car->_carName, car->_carName); carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carName = GfParmGetName(carparam); GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, car->_bestLapTime); GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName); GfParmSetNum(results, path, RE_ATTR_IDX, NULL, car->_driverIndex); snprintf(path2, BUFSIZE, "%s/%s/%d", race, RM_SECT_POINTS, i + 1); GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, (int)GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0)); GfParmReleaseHandle(carparam); break; } }
static void common_drive(int index, tCarElt* car, tSituation *s) { tdble slip; tdble ax0; tdble brake; tdble clutch; tdble throttle; tdble leftSteer; tdble rightSteer; int scrw, scrh, dummy; int idx = index - 1; tControlCmd *cmd = HCtx[idx]->CmdControl; const int BUFSIZE = 1024; char sstring[BUFSIZE]; static int firstTime = 1; if (firstTime) { if (HCtx[idx]->MouseControlUsed) { GfuiMouseShow(); GfctrlMouseInitCenter(); } GfuiKeyEventRegisterCurrent(onKeyAction); GfuiSKeyEventRegisterCurrent(onSKeyAction); firstTime = 0; } HCtx[idx]->distToStart = RtGetDistFromStart(car); HCtx[idx]->Gear = (tdble)car->_gear; /* telemetry */ GfScrGetSize(&scrw, &scrh, &dummy, &dummy); memset(&(car->ctrl), 0, sizeof(tCarCtrl)); car->_lightCmd = HCtx[idx]->lightCmd; if (car->_laps != HCtx[idx]->LastPitStopLap) { car->_raceCmd = RM_CMD_PIT_ASKED; } if (lastKeyUpdate != s->currentTime) { /* Update the controls only once for all the players */ updateKeys(); if (joyPresent) { GfctrlJoyGetCurrent(joyInfo); } GfctrlMouseGetCurrent(mouseInfo); lastKeyUpdate = s->currentTime; } if (((cmd[CMD_ABS].type == GFCTRL_TYPE_JOY_BUT) && joyInfo->edgeup[cmd[CMD_ABS].val]) || ((cmd[CMD_ABS].type == GFCTRL_TYPE_KEYBOARD) && keyInfo[cmd[CMD_ABS].val].edgeUp) || ((cmd[CMD_ABS].type == GFCTRL_TYPE_SKEYBOARD) && skeyInfo[cmd[CMD_ABS].val].edgeUp)) { HCtx[idx]->ParamAbs = 1 - HCtx[idx]->ParamAbs; snprintf(sstring, BUFSIZE, "%s/%s/%d", HM_SECT_PREF, HM_LIST_DRV, index); GfParmSetStr(PrefHdle, sstring, HM_ATT_ABS, Yn[1 - HCtx[idx]->ParamAbs]); GfParmWriteFile(NULL, PrefHdle, "Human"); } if (((cmd[CMD_ASR].type == GFCTRL_TYPE_JOY_BUT) && joyInfo->edgeup[cmd[CMD_ASR].val]) || ((cmd[CMD_ASR].type == GFCTRL_TYPE_KEYBOARD) && keyInfo[cmd[CMD_ASR].val].edgeUp) || ((cmd[CMD_ASR].type == GFCTRL_TYPE_SKEYBOARD) && skeyInfo[cmd[CMD_ASR].val].edgeUp)) { HCtx[idx]->ParamAsr = 1 - HCtx[idx]->ParamAsr; snprintf(sstring, BUFSIZE, "%s/%s/%d", HM_SECT_PREF, HM_LIST_DRV, index); GfParmSetStr(PrefHdle, sstring, HM_ATT_ASR, Yn[1 - HCtx[idx]->ParamAsr]); GfParmWriteFile(NULL, PrefHdle, "Human"); } const int bufsize = sizeof(car->_msgCmd[0]); snprintf(car->_msgCmd[0], bufsize, "%s %s", (HCtx[idx]->ParamAbs ? "ABS" : ""), (HCtx[idx]->ParamAsr ? "ASR" : "")); memcpy(car->_msgColorCmd, color, sizeof(car->_msgColorCmd)); if (((cmd[CMD_SPDLIM].type == GFCTRL_TYPE_JOY_BUT) && (joyInfo->levelup[cmd[CMD_SPDLIM].val] == 1)) || ((cmd[CMD_SPDLIM].type == GFCTRL_TYPE_KEYBOARD) && (keyInfo[cmd[CMD_SPDLIM].val].state == GFUI_KEY_DOWN)) || ((cmd[CMD_SPDLIM].type == GFCTRL_TYPE_SKEYBOARD) && (skeyInfo[cmd[CMD_SPDLIM].val].state == GFUI_KEY_DOWN))) { speedLimiter = 1; snprintf(car->_msgCmd[1], bufsize, "Speed Limiter On"); } else { speedLimiter = 0; snprintf(car->_msgCmd[1], bufsize, "Speed Limiter Off"); } if (((cmd[CMD_LIGHT1].type == GFCTRL_TYPE_JOY_BUT) && joyInfo->edgeup[cmd[CMD_LIGHT1].val]) || ((cmd[CMD_LIGHT1].type == GFCTRL_TYPE_KEYBOARD) && keyInfo[cmd[CMD_LIGHT1].val].edgeUp) || ((cmd[CMD_LIGHT1].type == GFCTRL_TYPE_SKEYBOARD) && skeyInfo[cmd[CMD_LIGHT1].val].edgeUp)) { if (HCtx[idx]->lightCmd & RM_LIGHT_HEAD1) { HCtx[idx]->lightCmd &= ~(RM_LIGHT_HEAD1 | RM_LIGHT_HEAD2); } else { HCtx[idx]->lightCmd |= RM_LIGHT_HEAD1 | RM_LIGHT_HEAD2; } } switch (cmd[CMD_LEFTSTEER].type) { case GFCTRL_TYPE_JOY_AXIS: ax0 = joyInfo->ax[cmd[CMD_LEFTSTEER].val] + cmd[CMD_LEFTSTEER].deadZone; if (ax0 > cmd[CMD_LEFTSTEER].max) { ax0 = cmd[CMD_LEFTSTEER].max; } else if (ax0 < cmd[CMD_LEFTSTEER].min) { ax0 = cmd[CMD_LEFTSTEER].min; } // normalize ax0 to -1..0 ax0 = (ax0 - cmd[CMD_LEFTSTEER].max) / (cmd[CMD_LEFTSTEER].max - cmd[CMD_LEFTSTEER].min); leftSteer = -SIGN(ax0) * cmd[CMD_LEFTSTEER].pow * pow(fabs(ax0), cmd[CMD_LEFTSTEER].sens) / (1.0 + cmd[CMD_LEFTSTEER].spdSens * car->pub.speed); break; case GFCTRL_TYPE_MOUSE_AXIS: ax0 = mouseInfo->ax[cmd[CMD_LEFTSTEER].val] - cmd[CMD_LEFTSTEER].deadZone; //FIXME: correct? if (ax0 > cmd[CMD_LEFTSTEER].max) { ax0 = cmd[CMD_LEFTSTEER].max; } else if (ax0 < cmd[CMD_LEFTSTEER].min) { ax0 = cmd[CMD_LEFTSTEER].min; } ax0 = ax0 * cmd[CMD_LEFTSTEER].pow; leftSteer = pow(fabs(ax0), cmd[CMD_LEFTSTEER].sens) / (1.0 + cmd[CMD_LEFTSTEER].spdSens * car->pub.speed / 10.0); break; case GFCTRL_TYPE_KEYBOARD: case GFCTRL_TYPE_SKEYBOARD: case GFCTRL_TYPE_JOY_BUT: if (cmd[CMD_LEFTSTEER].type == GFCTRL_TYPE_KEYBOARD) { ax0 = keyInfo[cmd[CMD_LEFTSTEER].val].state; } else if (cmd[CMD_LEFTSTEER].type == GFCTRL_TYPE_SKEYBOARD) { ax0 = skeyInfo[cmd[CMD_LEFTSTEER].val].state; } else { ax0 = joyInfo->levelup[cmd[CMD_LEFTSTEER].val]; } if (ax0 == 0) { HCtx[idx]->prevLeftSteer = leftSteer = 0; } else { ax0 = 2 * ax0 - 1; leftSteer = HCtx[idx]->prevLeftSteer + ax0 * cmd[CMD_LEFTSTEER].sens * s->deltaTime / (1.0 + cmd[CMD_LEFTSTEER].spdSens * car->pub.speed / 10.0); if (leftSteer > 1.0) leftSteer = 1.0; if (leftSteer < 0.0) leftSteer = 0.0; HCtx[idx]->prevLeftSteer = leftSteer; } break; default: leftSteer = 0; break; } switch (cmd[CMD_RIGHTSTEER].type) { case GFCTRL_TYPE_JOY_AXIS: ax0 = joyInfo->ax[cmd[CMD_RIGHTSTEER].val] - cmd[CMD_RIGHTSTEER].deadZone; if (ax0 > cmd[CMD_RIGHTSTEER].max) { ax0 = cmd[CMD_RIGHTSTEER].max; } else if (ax0 < cmd[CMD_RIGHTSTEER].min) { ax0 = cmd[CMD_RIGHTSTEER].min; } // normalize ax to 0..1 ax0 = (ax0 - cmd[CMD_RIGHTSTEER].min) / (cmd[CMD_RIGHTSTEER].max - cmd[CMD_RIGHTSTEER].min); rightSteer = -SIGN(ax0) * cmd[CMD_RIGHTSTEER].pow * pow(fabs(ax0), cmd[CMD_RIGHTSTEER].sens) / (1.0 + cmd[CMD_RIGHTSTEER].spdSens * car->pub.speed); break; case GFCTRL_TYPE_MOUSE_AXIS: ax0 = mouseInfo->ax[cmd[CMD_RIGHTSTEER].val] - cmd[CMD_RIGHTSTEER].deadZone; if (ax0 > cmd[CMD_RIGHTSTEER].max) { ax0 = cmd[CMD_RIGHTSTEER].max; } else if (ax0 < cmd[CMD_RIGHTSTEER].min) { ax0 = cmd[CMD_RIGHTSTEER].min; } ax0 = ax0 * cmd[CMD_RIGHTSTEER].pow; rightSteer = - pow(fabs(ax0), cmd[CMD_RIGHTSTEER].sens) / (1.0 + cmd[CMD_RIGHTSTEER].spdSens * car->pub.speed / 10.0); break; case GFCTRL_TYPE_KEYBOARD: case GFCTRL_TYPE_SKEYBOARD: case GFCTRL_TYPE_JOY_BUT: if (cmd[CMD_RIGHTSTEER].type == GFCTRL_TYPE_KEYBOARD) { ax0 = keyInfo[cmd[CMD_RIGHTSTEER].val].state; } else if (cmd[CMD_RIGHTSTEER].type == GFCTRL_TYPE_SKEYBOARD) { ax0 = skeyInfo[cmd[CMD_RIGHTSTEER].val].state; } else { ax0 = joyInfo->levelup[cmd[CMD_RIGHTSTEER].val]; } if (ax0 == 0) { HCtx[idx]->prevRightSteer = rightSteer = 0; } else { ax0 = 2 * ax0 - 1; rightSteer = HCtx[idx]->prevRightSteer - ax0 * cmd[CMD_RIGHTSTEER].sens * s->deltaTime/ (1.0 + cmd[CMD_RIGHTSTEER].spdSens * car->pub.speed / 10.0); if (rightSteer > 0.0) rightSteer = 0.0; if (rightSteer < -1.0) rightSteer = -1.0; HCtx[idx]->prevRightSteer = rightSteer; } break; default: rightSteer = 0; break; } car->_steerCmd = leftSteer + rightSteer; switch (cmd[CMD_BRAKE].type) { case GFCTRL_TYPE_JOY_AXIS: brake = joyInfo->ax[cmd[CMD_BRAKE].val]; if (brake > cmd[CMD_BRAKE].max) { brake = cmd[CMD_BRAKE].max; } else if (brake < cmd[CMD_BRAKE].min) { brake = cmd[CMD_BRAKE].min; } car->_brakeCmd = fabs(cmd[CMD_BRAKE].pow * pow(fabs((brake - cmd[CMD_BRAKE].minVal) / (cmd[CMD_BRAKE].max - cmd[CMD_BRAKE].min)), cmd[CMD_BRAKE].sens)); break; case GFCTRL_TYPE_MOUSE_AXIS: ax0 = mouseInfo->ax[cmd[CMD_BRAKE].val] - cmd[CMD_BRAKE].deadZone; if (ax0 > cmd[CMD_BRAKE].max) { ax0 = cmd[CMD_BRAKE].max; } else if (ax0 < cmd[CMD_BRAKE].min) { ax0 = cmd[CMD_BRAKE].min; } ax0 = ax0 * cmd[CMD_BRAKE].pow; car->_brakeCmd = pow(fabs(ax0), cmd[CMD_BRAKE].sens) / (1.0 + cmd[CMD_BRAKE].spdSens * car->_speed_x / 10.0); break; case GFCTRL_TYPE_JOY_BUT: car->_brakeCmd = joyInfo->levelup[cmd[CMD_BRAKE].val]; break; case GFCTRL_TYPE_MOUSE_BUT: car->_brakeCmd = mouseInfo->button[cmd[CMD_BRAKE].val]; break; case GFCTRL_TYPE_KEYBOARD: car->_brakeCmd = keyInfo[cmd[CMD_BRAKE].val].state; break; case GFCTRL_TYPE_SKEYBOARD: car->_brakeCmd = skeyInfo[cmd[CMD_BRAKE].val].state; break; default: car->_brakeCmd = 0; break; } switch (cmd[CMD_CLUTCH].type) { case GFCTRL_TYPE_JOY_AXIS: clutch = joyInfo->ax[cmd[CMD_CLUTCH].val]; if (clutch > cmd[CMD_CLUTCH].max) { clutch = cmd[CMD_CLUTCH].max; } else if (clutch < cmd[CMD_CLUTCH].min) { clutch = cmd[CMD_CLUTCH].min; } car->_clutchCmd = fabs(cmd[CMD_CLUTCH].pow * pow(fabs((clutch - cmd[CMD_CLUTCH].minVal) / (cmd[CMD_CLUTCH].max - cmd[CMD_CLUTCH].min)), cmd[CMD_CLUTCH].sens)); break; case GFCTRL_TYPE_MOUSE_AXIS: ax0 = mouseInfo->ax[cmd[CMD_CLUTCH].val] - cmd[CMD_CLUTCH].deadZone; if (ax0 > cmd[CMD_CLUTCH].max) { ax0 = cmd[CMD_CLUTCH].max; } else if (ax0 < cmd[CMD_CLUTCH].min) { ax0 = cmd[CMD_CLUTCH].min; } ax0 = ax0 * cmd[CMD_CLUTCH].pow; car->_clutchCmd = pow(fabs(ax0), cmd[CMD_CLUTCH].sens) / (1.0 + cmd[CMD_CLUTCH].spdSens * car->_speed_x / 10.0); break; case GFCTRL_TYPE_JOY_BUT: car->_clutchCmd = joyInfo->levelup[cmd[CMD_CLUTCH].val]; break; case GFCTRL_TYPE_MOUSE_BUT: car->_clutchCmd = mouseInfo->button[cmd[CMD_CLUTCH].val]; break; case GFCTRL_TYPE_KEYBOARD: car->_clutchCmd = keyInfo[cmd[CMD_CLUTCH].val].state; break; case GFCTRL_TYPE_SKEYBOARD: car->_clutchCmd = skeyInfo[cmd[CMD_CLUTCH].val].state; break; default: car->_clutchCmd = 0; break; } // if player's used the clutch manually then we dispense with autoClutch if (car->_clutchCmd != 0.0f) HCtx[idx]->autoClutch = 0; switch (cmd[CMD_THROTTLE].type) { case GFCTRL_TYPE_JOY_AXIS: throttle = joyInfo->ax[cmd[CMD_THROTTLE].val]; if (throttle > cmd[CMD_THROTTLE].max) { throttle = cmd[CMD_THROTTLE].max; } else if (throttle < cmd[CMD_THROTTLE].min) { throttle = cmd[CMD_THROTTLE].min; } car->_accelCmd = fabs(cmd[CMD_THROTTLE].pow * pow(fabs((throttle - cmd[CMD_THROTTLE].minVal) / (cmd[CMD_THROTTLE].max - cmd[CMD_THROTTLE].min)), cmd[CMD_THROTTLE].sens)); break; case GFCTRL_TYPE_MOUSE_AXIS: ax0 = mouseInfo->ax[cmd[CMD_THROTTLE].val] - cmd[CMD_THROTTLE].deadZone; if (ax0 > cmd[CMD_THROTTLE].max) { ax0 = cmd[CMD_THROTTLE].max; } else if (ax0 < cmd[CMD_THROTTLE].min) { ax0 = cmd[CMD_THROTTLE].min; } ax0 = ax0 * cmd[CMD_THROTTLE].pow; car->_accelCmd = pow(fabs(ax0), cmd[CMD_THROTTLE].sens) / (1.0 + cmd[CMD_THROTTLE].spdSens * car->_speed_x / 10.0); if (isnan (car->_accelCmd)) { car->_accelCmd = 0; } /* printf(" axO:%f accelCmd:%f\n", ax0, car->_accelCmd); */ break; case GFCTRL_TYPE_JOY_BUT: car->_accelCmd = joyInfo->levelup[cmd[CMD_THROTTLE].val]; break; case GFCTRL_TYPE_MOUSE_BUT: car->_accelCmd = mouseInfo->button[cmd[CMD_THROTTLE].val]; break; case GFCTRL_TYPE_KEYBOARD: car->_accelCmd = keyInfo[cmd[CMD_THROTTLE].val].state; break; case GFCTRL_TYPE_SKEYBOARD: car->_accelCmd = skeyInfo[cmd[CMD_THROTTLE].val].state; break; default: car->_accelCmd = 0; break; } if (s->currentTime > 1.0) { // thanks Christos for the following: gradual accel/brake changes for on/off controls. const tdble inc_rate = 0.2f; if (cmd[CMD_BRAKE].type == GFCTRL_TYPE_JOY_BUT || cmd[CMD_BRAKE].type == GFCTRL_TYPE_MOUSE_BUT || cmd[CMD_BRAKE].type == GFCTRL_TYPE_KEYBOARD || cmd[CMD_BRAKE].type == GFCTRL_TYPE_SKEYBOARD) { tdble d_brake = car->_brakeCmd - HCtx[idx]->pbrake; if (fabs(d_brake) > inc_rate && car->_brakeCmd > HCtx[idx]->pbrake) { car->_brakeCmd = MIN(car->_brakeCmd, HCtx[idx]->pbrake + inc_rate*d_brake/fabs(d_brake)); } HCtx[idx]->pbrake = car->_brakeCmd; } if (cmd[CMD_THROTTLE].type == GFCTRL_TYPE_JOY_BUT || cmd[CMD_THROTTLE].type == GFCTRL_TYPE_MOUSE_BUT || cmd[CMD_THROTTLE].type == GFCTRL_TYPE_KEYBOARD || cmd[CMD_THROTTLE].type == GFCTRL_TYPE_SKEYBOARD) { tdble d_accel = car->_accelCmd - HCtx[idx]->paccel; if (fabs(d_accel) > inc_rate && car->_accelCmd > HCtx[idx]->paccel) { car->_accelCmd = MIN(car->_accelCmd, HCtx[idx]->paccel + inc_rate*d_accel/fabs(d_accel)); } HCtx[idx]->paccel = car->_accelCmd; } } if (HCtx[idx]->AutoReverseEngaged) { /* swap brake and throttle */ brake = car->_brakeCmd; car->_brakeCmd = car->_accelCmd; car->_accelCmd = brake; } if (HCtx[idx]->ParamAbs) { if (fabs(car->_speed_x) > 10.0) { int i; tdble skidAng = atan2(car->_speed_Y, car->_speed_X) - car->_yaw; NORM_PI_PI(skidAng); if (car->_speed_x > 5 && fabs(skidAng) > 0.2) car->_brakeCmd = MIN(car->_brakeCmd, 0.10 + 0.70 * cos(skidAng)); if (fabs(car->_steerCmd) > 0.1) { tdble decel = ((fabs(car->_steerCmd)-0.1) * (1.0 + fabs(car->_steerCmd)) * 0.6); car->_brakeCmd = MIN(car->_brakeCmd, MAX(0.35, 1.0 - decel)); } const tdble abs_slip = 2.5; const tdble abs_range = 5.0; slip = 0; for (i = 0; i < 4; i++) { slip += car->_wheelSpinVel(i) * car->_wheelRadius(i); } slip = car->_speed_x - slip/4.0f; if (slip > abs_slip) car->_brakeCmd = car->_brakeCmd - MIN(car->_brakeCmd*0.8, (slip - abs_slip) / abs_range); } } if (HCtx[idx]->ParamAsr) { tdble trackangle = RtTrackSideTgAngleL(&(car->_trkPos)); tdble angle = trackangle - car->_yaw; NORM_PI_PI(angle); tdble maxaccel = 0.0; if (car->_trkPos.seg->type == TR_STR) maxaccel = MIN(car->_accelCmd, 0.2); else if (car->_trkPos.seg->type == TR_LFT && angle < 0.0) maxaccel = MIN(car->_accelCmd, MIN(0.6, -angle)); else if (car->_trkPos.seg->type == TR_RGT && angle > 0.0) maxaccel = MIN(car->_accelCmd, MIN(0.6, angle)); tdble origaccel = car->_accelCmd; tdble skidAng = atan2(car->_speed_Y, car->_speed_X) - car->_yaw; NORM_PI_PI(skidAng); if (car->_speed_x > 5 && fabs(skidAng) > 0.2) { car->_accelCmd = MIN(car->_accelCmd, 0.15 + 0.70 * cos(skidAng)); car->_accelCmd = MAX(car->_accelCmd, maxaccel); } if (fabs(car->_steerCmd) > 0.1) { tdble decel = ((fabs(car->_steerCmd)-0.1) * (1.0 + fabs(car->_steerCmd)) * 0.8); car->_accelCmd = MIN(car->_accelCmd, MAX(0.35, 1.0 - decel)); } tdble drivespeed = 0.0; switch (HCtx[idx]->drivetrain) { case D4WD: drivespeed = ((car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * car->_wheelRadius(FRNT_LFT) + (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * car->_wheelRadius(REAR_LFT)) / 4.0; break; case DFWD: drivespeed = (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * car->_wheelRadius(FRNT_LFT) / 2.0; break; default: drivespeed = (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * car->_wheelRadius(REAR_LFT) / 2.0; break; } tdble slip = drivespeed - fabs(car->_speed_x); if (slip > 2.0) car->_accelCmd = MIN(car->_accelCmd, origaccel - MIN(origaccel-0.1, ((slip - 2.0)/10.0))); } if (speedLimiter) { tdble Dv; if (Vtarget != 0) { Dv = Vtarget - car->_speed_x; if (Dv > 0.0) { car->_accelCmd = MIN(car->_accelCmd, fabs(Dv/6.0)); } else { car->_brakeCmd = MAX(car->_brakeCmd, fabs(Dv/5.0)); car->_accelCmd = 0; } } } #ifndef WIN32 #ifdef TELEMETRY if ((car->_laps > 1) && (car->_laps < 5)) { if (HCtx[idx]->lap == 1) { RtTelemStartMonitoring("Player"); } RtTelemUpdate(car->_curLapTime); } if (car->_laps == 5) { if (HCtx[idx]->lap == 4) { RtTelemShutdown(); } } #endif #endif HCtx[idx]->lap = car->_laps; }