/*************************************************************************** file : racemain.cpp created : Sat Nov 16 12:13:31 CET 2002 copyright : (C) 2002 by Eric Espié email : eric.espie@torcs.org version : $Id: racemain.cpp,v 1.13 2005/08/17 20:48:39 berniw Exp $ ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** @file @author Eric Espie @version $Id: racemain.cpp,v 1.13 2005/08/17 20:48:39 berniw Exp $ */ #include #include #include #include #include #include #include #include "raceengine.h" #include "raceinit.h" #include "racegl.h" #include "raceresults.h" #include "racestate.h" #include "racemanmenu.h" #include "racemain.h" static char buf[1024]; static char path[1024]; static char path2[1024]; /***************************************************************/ /* ABANDON RACE HOOK */ static void *AbandonRaceHookHandle = 0; static void AbandonRaceHookActivate(void * /* vforce */) { // Shutdown current event. ReEventShutdown(); /* Return to race menu */ ReInfo->_reState = RE_STATE_CONFIG; GfuiScreenActivate(ReInfo->_reGameScreen); } static void * AbandonRaceHookInit(void) { if (AbandonRaceHookHandle) { return AbandonRaceHookHandle; } AbandonRaceHookHandle = GfuiHookCreate(0, AbandonRaceHookActivate); return AbandonRaceHookHandle; } static void *AbortRaceHookHandle = 0; static void AbortRaceHookActivate(void * /* dummy */) { GfuiScreenActivate(ReInfo->_reGameScreen); ReInfo->_reSimItf.shutdown(); if (ReInfo->_displayMode == RM_DISP_MODE_NORMAL) { ReInfo->_reGraphicItf.shutdowncars(); } ReInfo->_reGraphicItf.shutdowntrack(); ReRaceCleanDrivers(); FREEZ(ReInfo->_reCarInfo); /* Return to race menu */ ReInfo->_reState = RE_STATE_CONFIG; } static void * AbortRaceHookInit(void) { if (AbortRaceHookHandle) { return AbortRaceHookHandle; } AbortRaceHookHandle = GfuiHookCreate(0, AbortRaceHookActivate); return AbortRaceHookHandle; } int ReRaceEventInit(void) { void *params = ReInfo->params; RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png"); ReInitTrack(); RmLoadingScreenSetText("Loading Track 3D Description..."); ReInfo->_reGraphicItf.inittrack(ReInfo->track); ReEventInitResults(); if (GfParmGetEltNb(params, RM_SECT_TRACKS) > 1) { ReNewTrackMenu(); return RM_ASYNC | RM_NEXT_STEP; } return RM_SYNC | RM_NEXT_STEP; } int RePreRace(void) { tdble dist; char *raceName; char *raceType; void *params = ReInfo->params; void *results = ReInfo->results; raceName = ReInfo->_reRaceName = ReGetCurrentRaceName(); if (!raceName) { return RM_QUIT; } dist = GfParmGetNum(params, raceName, RM_ATTR_DISTANCE, NULL, 0); if (dist < 0.001) { ReInfo->s->_totLaps = (int)GfParmGetNum(params, raceName, RM_ATTR_LAPS, NULL, 30); } else { ReInfo->s->_totLaps = ((int)(dist / ReInfo->track->length)) + 1; } ReInfo->s->_maxDammage = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DMG, NULL, 10000); raceType = GfParmGetStr(params, raceName, RM_ATTR_TYPE, RM_VAL_RACE); if (!strcmp(raceType, RM_VAL_RACE)) { ReInfo->s->_raceType = RM_TYPE_RACE; } else if (!strcmp(raceType, RM_VAL_QUALIF)) { ReInfo->s->_raceType = RM_TYPE_QUALIF; } else if (!strcmp(raceType, RM_VAL_PRACTICE)) { ReInfo->s->_raceType = RM_TYPE_PRACTICE; } ReInfo->s->_raceState = 0; /* Cleanup results */ sprintf(path, "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, raceName); GfParmListClean(results, path); return RM_SYNC | RM_NEXT_STEP; } /* return state mode */ static int reRaceRealStart(void) { int i, j; int sw, sh, vw, vh; tRobotItf *robot; tReCarInfo *carInfo; char *dllname; char key[256]; int foundHuman; void *params = ReInfo->params; void *results = ReInfo->results; tSituation *s = ReInfo->s; RmLoadingScreenSetText("Loading Simulation Engine..."); dllname = GfParmGetStr(ReInfo->_reParam, "Modules", "simu", ""); sprintf(key, "%smodules/simu/%s.%s", GetLibDir (), dllname, DLLEXT); if (GfModLoad(0, key, &ReRaceModList)) return RM_QUIT; ReRaceModList->modInfo->fctInit(ReRaceModList->modInfo->index, &ReInfo->_reSimItf); if (ReInitCars()) { return RM_QUIT; } /* Blind mode or not */ ReInfo->_displayMode = RM_DISP_MODE_NORMAL; ReInfo->_reGameScreen = ReScreenInit(); foundHuman = 0; for (i = 0; i < s->_ncars; i++) { if (s->cars[i]->_driverType == RM_DRV_HUMAN) { foundHuman = 1; break; } } if (!foundHuman) { if (!strcmp(GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_DISPMODE, RM_VAL_VISIBLE), RM_VAL_INVISIBLE)) { ReInfo->_displayMode = RM_DISP_MODE_NONE; ReInfo->_reGameScreen = ReResScreenInit(); } } if (!(ReInfo->s->_raceType == RM_TYPE_QUALIF) || ((int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1) == 1)) { RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png"); } for (i = 0; i < s->_ncars; i++) { sprintf(buf, "Initializing Driver %s...", s->cars[i]->_name); RmLoadingScreenSetText(buf); robot = s->cars[i]->robot; robot->rbNewRace(robot->index, s->cars[i], s); } carInfo = ReInfo->_reCarInfo; ReInfo->_reSimItf.update(s, RCM_MAX_DT_SIMU, -1); for (i = 0; i < s->_ncars; i++) { carInfo[i].prevTrkPos = s->cars[i]->_trkPos; } RmLoadingScreenSetText("Running Prestart..."); for (i = 0; i < s->_ncars; i++) { memset(&(s->cars[i]->ctrl), 0, sizeof(tCarCtrl)); s->cars[i]->ctrl.brakeCmd = 1.0; } for (j = 0; j < ((int)(1.0 / RCM_MAX_DT_SIMU)); j++) { ReInfo->_reSimItf.update(s, RCM_MAX_DT_SIMU, -1); } if (ReInfo->_displayMode != RM_DISP_MODE_NORMAL) { if (ReInfo->s->_raceType == RM_TYPE_QUALIF) { ReUpdateQualifCurRes(s->cars[0]); } else { sprintf(buf, "%s on %s", s->cars[0]->_name, ReInfo->track->name); ReResScreenSetTitle(buf); } } RmLoadingScreenSetText("Ready."); ReInfo->_reTimeMult = 1.0; ReInfo->_reLastTime = -1.0; ReInfo->s->currentTime = -2.0; ReInfo->s->deltaTime = RCM_MAX_DT_SIMU; ReInfo->s->_raceState = RM_RACE_STARTING; GfScrGetSize(&sw, &sh, &vw, &vh); ReInfo->_reGraphicItf.initview((sw-vw)/2, (sh-vh)/2, vw, vh, GR_VIEW_STD, ReInfo->_reGameScreen); if (ReInfo->_displayMode == RM_DISP_MODE_NORMAL) { /* RmLoadingScreenSetText("Loading Cars 3D Objects..."); */ ReInfo->_reGraphicItf.initcars(s); } GfuiScreenActivate(ReInfo->_reGameScreen); return RM_SYNC | RM_NEXT_STEP; } /***************************************************************/ /* START RACE HOOK */ static void *StartRaceHookHandle = 0; static void StartRaceHookActivate(void * /* dummy */) { reRaceRealStart(); } static void * StartRaceHookInit(void) { if (StartRaceHookHandle) { return StartRaceHookHandle; } StartRaceHookHandle = GfuiHookCreate(0, StartRaceHookActivate); return StartRaceHookHandle; } /* return state mode */ int ReRaceStart(void) { int i; int nCars; int maxCars; char *prevRaceName; char *gridType; char *raceName = ReInfo->_reRaceName; void *params = ReInfo->params; void *results = ReInfo->results; 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(); } sprintf(path, "%s/%d", RM_SECT_DRIVERS, i); sprintf(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)); } else { RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png"); RmLoadingScreenSetText("Preparing Starting Grid..."); 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); prevRaceName = ReGetPrevRaceName(); if (!prevRaceName) { return RM_QUIT; } for (i = 1; i < nCars + 1; i++) { sprintf(path, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, i); sprintf(path2, "%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); prevRaceName = ReGetPrevRaceName(); if (!prevRaceName) { return RM_QUIT; } for (i = 1; i < nCars + 1; i++) { sprintf(path, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, nCars - i + 1); sprintf(path2, "%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++) { sprintf(path, "%s/%d", RM_SECT_DRIVERS, i); sprintf(path2, "%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 (!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(); } /***************************************************************/ /* BACK TO RACE HOOK */ static void *BackToRaceHookHandle = 0; static void BackToRaceHookActivate(void * /* dummy */) { ReInfo->_reState = RE_STATE_RACE; GfuiScreenActivate(ReInfo->_reGameScreen); } static void * BackToRaceHookInit(void) { if (BackToRaceHookHandle) { return BackToRaceHookHandle; } BackToRaceHookHandle = GfuiHookCreate(0, BackToRaceHookActivate); return BackToRaceHookHandle; } /***************************************************************/ /* RESTART RACE HOOK */ static void *RestartRaceHookHandle = 0; static void RestartRaceHookActivate(void * /* dummy */) { ReRaceCleanup(); ReInfo->_reState = RE_STATE_PRE_RACE; GfuiScreenActivate(ReInfo->_reGameScreen); } static void * RestartRaceHookInit(void) { if (RestartRaceHookHandle) { return RestartRaceHookHandle; } RestartRaceHookHandle = GfuiHookCreate(0, RestartRaceHookActivate); return RestartRaceHookHandle; } /***************************************************************/ /* QUIT HOOK */ static void *QuitHookHandle = 0; static void *StopScrHandle = 0; static void QuitHookActivate(void * /* dummy */) { if (StopScrHandle) { GfuiScreenActivate(TorcsExitMenuInit(StopScrHandle)); } } static void * QuitHookInit(void) { if (QuitHookHandle) { return QuitHookHandle; } QuitHookHandle = GfuiHookCreate(0, QuitHookActivate); return QuitHookHandle; } int ReRaceStop(void) { void *params = ReInfo->params; if (!strcmp(GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_ALLOW_RESTART, RM_VAL_NO), RM_VAL_NO)) { StopScrHandle = RmTriStateScreen("Race Stopped", "Abandon Race", "Abort current race", AbortRaceHookInit(), "Resume Race", "Return to Race", BackToRaceHookInit(), "Quit Game", "Quit the game", QuitHookInit()); } else { StopScrHandle = RmFourStateScreen("Race Stopped", "Restart Race", "Restart the current race", RestartRaceHookInit(), "Abandon Race", "Abort current race", AbortRaceHookInit(), "Resume Race", "Return to Race", BackToRaceHookInit(), "Quit Game", "Quit the game", QuitHookInit()); } return RM_ASYNC | RM_NEXT_STEP; } int ReRaceEnd(void) { int curDrvIdx; void *params = ReInfo->params; void *results = ReInfo->results; ReRaceCleanup(); if (ReInfo->s->_raceType == RM_TYPE_QUALIF) { curDrvIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1); curDrvIdx++; if (curDrvIdx > GfParmGetEltNb(params, RM_SECT_DRIVERS)) { GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1); return ReDisplayResults(); } GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, curDrvIdx); return RM_SYNC | RM_NEXT_RACE; } return ReDisplayResults(); } int RePostRace(void) { int curRaceIdx; void *results = ReInfo->results; void *params = ReInfo->params; //ReUpdateStandings(); curRaceIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1); if (curRaceIdx < GfParmGetEltNb(params, RM_SECT_RACES)) { curRaceIdx++; GfOut("Race Nb %d\n", curRaceIdx); GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, curRaceIdx); ReUpdateStandings(); return RM_SYNC | RM_NEXT_RACE; } ReUpdateStandings(); GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1); return RM_SYNC | RM_NEXT_STEP; } int ReEventShutdown(void) { int curTrkIdx; void *params = ReInfo->params; int nbTrk = GfParmGetEltNb(params, RM_SECT_TRACKS); int ret = 0; void *results = ReInfo->results; ReInfo->_reGraphicItf.shutdowntrack(); int 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, curTrkIdx); if (curTrkIdx != 1) { ret = RM_NEXT_RACE; } else { ret = RM_NEXT_STEP; } if (nbTrk != 1) { ReDisplayStandings(); return RM_ASYNC | ret; } FREEZ(ReInfo->_reCarInfo); return RM_SYNC | ret; }