void ReUpdatePracticeCurRes(tCarElt *car, bool bForceNew) { if (bForceNew) { static const char* pszTableHeader = "Lap \tTime \tBest \tTop spd \tMin spd \tDamages"; ReUI().setResultsTableHeader(pszTableHeader); char* t1 = GfTime2Str(car->_lastLapTime, 0, false, 3); char* t2 = GfTime2Str(car->_bestLapTime, 0, false, 3); char buf[128]; // Cancel hightlight on first line if (car->_laps == 2) ReUI().setResultsTableRow(0, ""); tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); static int nLastLapDamages = 0; if (car->_laps <= 2) nLastLapDamages = 0; snprintf(buf, sizeof(buf), "%.3d \t%-12s \t%-12s \t%5.1f \t%5.1f \t %.5d (%d)", car->_laps - 1, t1, t2, info->topSpd * 3.6, info->botSpd * 3.6, car->_dammage ? car->_dammage - nLastLapDamages : 0, car->_dammage); nLastLapDamages = car->_dammage; free(t1); free(t2); ReUI().addResultsTableRow(buf); } else { ReUpdateQualifCurRes(car); } }
void ReInitCurRes() { if (ReInfo->_displayMode != RM_DISP_MODE_NORMAL) { if (ReInfo->s->_raceType == RM_TYPE_QUALIF) { ReUpdateQualifCurRes(ReInfo->s->cars[0]); } else if (ReInfo->s->_raceType == RM_TYPE_PRACTICE && ReInfo->s->_ncars > 1) { ReUpdatePracticeCurRes(ReInfo->s->cars[0]); } else { static const char* pszTableHeader = "Rank Time Driver Car"; char pszTitle[128]; snprintf(pszTitle, sizeof(pszTitle), "%s at %s", ReInfo->_reRaceName, ReInfo->track->name); char pszSubTitle[128]; snprintf(pszSubTitle, sizeof(pszSubTitle), "%s (%s)", ReInfo->s->cars[0]->_name, ReInfo->s->cars[0]->_carName); ReUI().setResultsTableTitles(pszTitle, pszSubTitle); ReUI().setResultsTableHeader(pszTableHeader); } }//if displayMode != normal }
void ReCarsManageCar(tCarElt *car, bool& bestLapChanged) { char msg[64]; int i; int xx; tTrackSeg *sseg; tdble wseg; static const float ctrlMsgColor[] = {0.0, 0.0, 1.0, 1.0}; tSituation *s = ReInfo->s; tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); // Update top speeds. if (car->_speed_x > car->_topSpeed) car->_topSpeed = car->_speed_x; // (practice and qualification only). if (car->_speed_x > info->topSpd) info->topSpd = car->_speed_x; if (car->_speed_x < info->botSpd) info->botSpd = car->_speed_x; // Pitstop management. if (car->_pit) { // If the driver can ask for a pit, update control messages whether slot occupied or not. if (car->ctrl.raceCmd & RM_CMD_PIT_ASKED) { // Pit already occupied? if (car->_pit->pitCarIndex == TR_PIT_STATE_FREE) snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Can Pit"); else snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Pit Occupied"); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. memcpy(car->ctrl.msgColor, ctrlMsgColor, sizeof(car->ctrl.msgColor)); } // If pitting, check if pitting delay over, and end up with pitting process if so. if (car->_state & RM_CAR_STATE_PIT) { car->ctrl.raceCmd &= ~RM_CMD_PIT_ASKED; // clear the flag. // Note: Due to asynchronous behaviour of the main updater and the situation updater, // we have to wait for car->_scheduledEventTime being set to smthg > 0. if (car->_scheduledEventTime > 0.0) { if (car->_scheduledEventTime < s->currentTime) { car->_state &= ~RM_CAR_STATE_PIT; car->_pit->pitCarIndex = TR_PIT_STATE_FREE; snprintf(msg, sizeof(msg), "%s pit stop %.1f s", car->_name, info->totalPitTime); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); GfLogInfo("%s exiting pit (%.1f s elapsed).\n", car->_name, info->totalPitTime); } else { snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "In pits %.1f s", s->currentTime - info->startPitTime); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. } } // If the driver asks for a pit, check if the car is in the right conditions // (position, speed, ...) and start up pitting process if so. } else if ((car->ctrl.raceCmd & RM_CMD_PIT_ASKED) && car->_pit->pitCarIndex == TR_PIT_STATE_FREE && (s->_maxDammage == 0 || car->_dammage <= s->_maxDammage)) { snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Pit request"); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. tdble lgFromStart = car->_trkPos.seg->lgfromstart; switch (car->_trkPos.seg->type) { case TR_STR: lgFromStart += car->_trkPos.toStart; break; default: lgFromStart += car->_trkPos.toStart * car->_trkPos.seg->radius; break; } if ((lgFromStart > car->_pit->lmin) && (lgFromStart < car->_pit->lmax)) { int side; tdble toBorder; if (ReInfo->track->pits.side == TR_RGT) { side = TR_SIDE_RGT; toBorder = car->_trkPos.toRight; } else { side = TR_SIDE_LFT; toBorder = car->_trkPos.toLeft; } sseg = car->_trkPos.seg->side[side]; wseg = RtTrackGetWidth(sseg, car->_trkPos.toStart); if (sseg->side[side]) { sseg = sseg->side[side]; wseg += RtTrackGetWidth(sseg, car->_trkPos.toStart); } if (((toBorder + wseg) < (ReInfo->track->pits.width - car->_dimension_y / 2.0)) && (fabs(car->_speed_x) < 1.0) && (fabs(car->_speed_y) < 1.0)) { // All conditions fullfilled => enter pitting process car->_state |= RM_CAR_STATE_PIT; car->_scheduledEventTime = 0.0; // Pit will really start when set to smthg > 0. car->_nbPitStops++; for (i = 0; i < car->_pit->freeCarIndex; i++) { if (car->_pit->car[i] == car) { car->_pit->pitCarIndex = i; break; } } info->startPitTime = s->currentTime; snprintf(msg, sizeof(msg), "%s in pits", car->_name); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); GfLogInfo("%s entering in pit slot.\n", car->_name); if (car->robot->rbPitCmd(car->robot->index, car, s) == ROB_PIT_MENU) { // the pit cmd is modified by menu. reCarsSchedulePitMenu(car); } else { ReCarsUpdateCarPitTime(car); } } else { // The cars speed or offset is out of accepted range // Show the user/developer/robot the reason of the issue tTeamDriver* TeamDriver = RtTeamDriverByCar(car); if (TeamDriver) { TeamDriver->StillToGo = 0.0; TeamDriver->MoreOffset = 0.0; TeamDriver->TooFastBy = 0.0; } float Offset = (float) ((toBorder + wseg) - (ReInfo->track->pits.width - car->_dimension_y / 2.0)); if (Offset >= 0.0) { // The car's position across the track is out of accepted range snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Offset: %.02f",Offset); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->MoreOffset = Offset; } float TooFastBy = MAX(fabs(car->_speed_x),fabs(car->_speed_y)); if (TooFastBy >= 1.0) { // The car's speed is out of accepted range snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Speed: %.02f",TooFastBy); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->TooFastBy = TooFastBy; } } } else { // The car's position along the track is out of accepted range // Show the user/developer/robot the reason of the issue tTeamDriver* TeamDriver = RtTeamDriverByCar(car); if (TeamDriver) { TeamDriver->StillToGo = 0.0; TeamDriver->MoreOffset = 0.0; TeamDriver->TooFastBy = 0.0; } if (car->_pit->lmin > lgFromStart) { float StillToGo = car->_pit->lmin - lgFromStart; snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Still to go: %0.2f m" ,StillToGo); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->StillToGo = StillToGo; } else if (car->_pit->lmax < lgFromStart) { float StillToGo = lgFromStart - car->_pit->lmax; snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Overrun: %0.2f m" ,StillToGo); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->StillToGo = -StillToGo; } } } } /* Check if it is in a new sector */ while (true) { if (car->_currentSector < ReInfo->track->numberOfSectors - 1 && car->_laps > 0 && info->lapFlag == 0) { /* Must pass at least one sector before the finish */ if (RtGetDistFromStart(car) > ReInfo->track->sectors[car->_currentSector]) { /* It is in a new sector : update split time */ car->_curSplitTime[car->_currentSector] = car->_curLapTime; ++car->_currentSector; continue; } } break; } /* Start Line Crossing */ if (info->prevTrkPos.seg != car->_trkPos.seg) { if ((info->prevTrkPos.seg->raceInfo & TR_LAST) && (car->_trkPos.seg->raceInfo & TR_START)) { if (info->lapFlag == 0) { // If the car has not yet finished the race : if (!(car->_state & RM_CAR_STATE_FINISH)) { // 1 more lap completed // (Note: lap with index 0 finishes when the car crosses the start line the 1st time, // and is thus considered a real lap, whereas it is not). car->_laps++; /*if (NetGetNetwork()) NetGetNetwork()->SendLapStatusPacket(car);*/ car->_remainingLaps--; if (car->_pos == 1 && s->currentTime < s->_totTime && s->_raceType == RM_TYPE_RACE) { /* First car passed finish time before the time ends: increase the number of laps for everyone */ for (xx = 0; xx < s->_ncars; ++xx) ++ReInfo->s->cars[xx]->_remainingLaps; ++s->_totLaps; } car->_currentSector = 0; if (car->_laps > 1) { car->_lastLapTime = s->currentTime - info->sTime; if (car->_bestLapTime != 0) { car->_deltaBestLapTime = car->_lastLapTime - car->_bestLapTime; } if ((car->_lastLapTime < car->_bestLapTime) || (car->_bestLapTime == 0)) { car->_bestLapTime = car->_lastLapTime; memcpy(car->_bestSplitTime, car->_curSplitTime, sizeof(double)*(ReInfo->track->numberOfSectors - 1) ); if (s->_raceType != RM_TYPE_RACE && s->_ncars > 1) { /* Best lap time is made better : update times behind leader */ bestLapChanged = true; car->_timeBehindLeader = car->_bestLapTime - s->cars[0]->_bestLapTime; if (car->_pos > 1) { car->_timeBehindPrev = car->_bestLapTime - s->cars[car->_pos - 1]->_bestLapTime; } else { /* New best time for the leader : update the differences */ for (xx = 1; xx < s->_ncars; ++xx) { if (s->cars[xx]->_bestLapTime > 0.0f) s->cars[xx]->_timeBehindLeader = s->cars[xx]->_bestLapTime - car->_bestLapTime; } } if (car->_pos + 1 < s->_ncars && s->cars[car->_pos+1]->_bestLapTime > 0.0f) car->_timeBeforeNext = s->cars[car->_pos + 1]->_bestLapTime - car->_bestLapTime; else car->_timeBeforeNext = 0; } } } if (car->_laps > 0) { car->_curTime += s->currentTime - info->sTime; if (car->_pos != 1 && s->_raceType == RM_TYPE_RACE) { car->_timeBehindLeader = car->_curTime - s->cars[0]->_curTime; car->_lapsBehindLeader = s->cars[0]->_laps - car->_laps; car->_timeBehindPrev = car->_curTime - s->cars[car->_pos - 2]->_curTime; s->cars[car->_pos - 2]->_timeBeforeNext = car->_timeBehindPrev; } else if (s->_raceType == RM_TYPE_RACE) { car->_timeBehindLeader = 0; car->_lapsBehindLeader = 0; car->_timeBehindPrev = 0; } info->sTime = (tdble)s->currentTime; if (ReInfo->s->_raceType == RM_TYPE_PRACTICE && (car->_laps > 1 || s->_totLaps == 0)) ReSavePracticeLap(car); } if (ReInfo->_displayMode == RM_DISP_MODE_NONE) { switch(s->_raceType) { case RM_TYPE_PRACTICE: ReUpdatePracticeCurRes(car); break; case RM_TYPE_QUALIF: ReUpdateQualifCurRes(car); break; case RM_TYPE_RACE: ReUpdateRaceCurRes(); break; default: break; } } info->topSpd = car->_speed_x; info->botSpd = car->_speed_x; if ((car->_remainingLaps < 0 && s->currentTime > s->_totTime) || (s->_raceState == RM_RACE_FINISHING)) { car->_state |= RM_CAR_STATE_FINISH; s->_raceState = RM_RACE_FINISHING; if (ReInfo->s->_raceType == RM_TYPE_RACE) { if (car->_pos == 1) { snprintf(msg, sizeof(msg), "Winner %s", car->_name); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 10, /*big=*/true); if (NetGetServer()) { NetGetServer()->SetFinishTime(s->currentTime+FINISHDELAY); } } else { const char *numSuffix = "th"; if (abs(12 - car->_pos) > 1) { /* leave suffix as 'th' for 11 to 13 */ switch (car->_pos % 10) { case 1: numSuffix = "st"; break; case 2: numSuffix = "nd"; break; case 3: numSuffix = "rd"; break; default: break; } } snprintf(msg, sizeof(msg), "%s finished %d%s", car->_name, car->_pos, numSuffix); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); } } } // Notify the UI when a lap is completed (by the leader) // and race results have been updated. if (car->_pos == 1) ReUI().onLapCompleted(car->_laps - 1); } else { // Prevent infinite looping of cars around track, // allowing one lap after finish for the first car, but no more for (i = 0; i < s->_ncars; i++) { s->cars[i]->_state |= RM_CAR_STATE_FINISH; } return; } } else { info->lapFlag--; } } if ((info->prevTrkPos.seg->raceInfo & TR_START) && (car->_trkPos.seg->raceInfo & TR_LAST)) { /* going backward through the start line */ info->lapFlag++; } } // Start Line Crossing // Apply race rules (penalties if enabled). reCarsApplyRaceRules(car); // Update misc car info. info->prevTrkPos = car->_trkPos; car->_curLapTime = s->currentTime - info->sTime; car->_distFromStartLine = car->_trkPos.seg->lgfromstart + (car->_trkPos.seg->type == TR_STR ? car->_trkPos.toStart : car->_trkPos.toStart * car->_trkPos.seg->radius); car->_distRaced = (car->_laps - 1) * ReInfo->track->length + car->_distFromStartLine; }
static void ReManage(tCarElt *car) { int i, pitok; tTrackSeg *sseg; tdble wseg; static float color[] = {0.0, 0.0, 1.0, 1.0}; tSituation *s = ReInfo->s; tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); if (car->_speed_x > car->_topSpeed) { car->_topSpeed = car->_speed_x; } // For practice and qualif. if (car->_speed_x > info->topSpd) { info->topSpd = car->_speed_x; } if (car->_speed_x < info->botSpd) { info->botSpd = car->_speed_x; } // Pitstop. if (car->_pit) { if (car->ctrl.raceCmd & RM_CMD_PIT_ASKED) { // Pit already occupied? if (car->_pit->pitCarIndex == TR_PIT_STATE_FREE) { sprintf(car->ctrl.msg[2], "Can Pit"); } else { sprintf(car->ctrl.msg[2], "Pit Occupied"); } memcpy(car->ctrl.msgColor, color, sizeof(car->ctrl.msgColor)); } if (car->_state & RM_CAR_STATE_PIT) { car->ctrl.raceCmd &= ~RM_CMD_PIT_ASKED; // clear the flag. if (car->_scheduledEventTime < s->currentTime) { car->_state &= ~RM_CAR_STATE_PIT; car->_pit->pitCarIndex = TR_PIT_STATE_FREE; sprintf(buf, "%s pit stop %.1fs", car->_name, info->totalPitTime); ReRaceMsgSet(buf, 5); } else { sprintf(car->ctrl.msg[2], "in pits %.1fs", s->currentTime - info->startPitTime); } } else if ((car->ctrl.raceCmd & RM_CMD_PIT_ASKED) && car->_pit->pitCarIndex == TR_PIT_STATE_FREE && (s->_maxDammage == 0 || car->_dammage <= s->_maxDammage)) { tdble lgFromStart = car->_trkPos.seg->lgfromstart; switch (car->_trkPos.seg->type) { case TR_STR: lgFromStart += car->_trkPos.toStart; break; default: lgFromStart += car->_trkPos.toStart * car->_trkPos.seg->radius; break; } if ((lgFromStart > car->_pit->lmin) && (lgFromStart < car->_pit->lmax)) { pitok = 0; int side; tdble toBorder; if (ReInfo->track->pits.side == TR_RGT) { side = TR_SIDE_RGT; toBorder = car->_trkPos.toRight; } else { side = TR_SIDE_LFT; toBorder = car->_trkPos.toLeft; } sseg = car->_trkPos.seg->side[side]; wseg = RtTrackGetWidth(sseg, car->_trkPos.toStart); if (sseg->side[side]) { sseg = sseg->side[side]; wseg += RtTrackGetWidth(sseg, car->_trkPos.toStart); } if (((toBorder + wseg) < (ReInfo->track->pits.width - car->_dimension_y / 2.0)) && (fabs(car->_speed_x) < 1.0) && (fabs(car->_speed_y) < 1.0)) { pitok = 1; } if (pitok) { car->_state |= RM_CAR_STATE_PIT; car->_nbPitStops++; for (i = 0; i < car->_pit->freeCarIndex; i++) { if (car->_pit->car[i] == car) { car->_pit->pitCarIndex = i; break; } } info->startPitTime = s->currentTime; sprintf(buf, "%s in pits", car->_name); ReRaceMsgSet(buf, 5); if (car->robot->rbPitCmd(car->robot->index, car, s) == ROB_PIT_MENU) { // the pit cmd is modified by menu. ReStop(); RmPitMenuStart(car, (void*)car, ReUpdtPitCmd); } else { ReUpdtPitTime(car); } } } } } /* Start Line Crossing */ if (info->prevTrkPos.seg != car->_trkPos.seg) { if ((info->prevTrkPos.seg->raceInfo & TR_LAST) && (car->_trkPos.seg->raceInfo & TR_START)) { if (info->lapFlag == 0) { if ((car->_state & RM_CAR_STATE_FINISH) == 0) { car->_laps++; car->_remainingLaps--; if (car->_laps > 1) { car->_lastLapTime = s->currentTime - info->sTime; car->_curTime += car->_lastLapTime; if (car->_bestLapTime != 0) { car->_deltaBestLapTime = car->_lastLapTime - car->_bestLapTime; } if ((car->_lastLapTime < car->_bestLapTime) || (car->_bestLapTime == 0)) { car->_bestLapTime = car->_lastLapTime; } if (car->_pos != 1) { car->_timeBehindLeader = car->_curTime - s->cars[0]->_curTime; car->_lapsBehindLeader = s->cars[0]->_laps - car->_laps; car->_timeBehindPrev = car->_curTime - s->cars[car->_pos - 2]->_curTime; s->cars[car->_pos - 2]->_timeBeforeNext = car->_timeBehindPrev; } else { car->_timeBehindLeader = 0; car->_lapsBehindLeader = 0; car->_timeBehindPrev = 0; } info->sTime = s->currentTime; switch (ReInfo->s->_raceType) { case RM_TYPE_PRACTICE: if (ReInfo->_displayMode == RM_DISP_MODE_NONE) { ReInfo->_refreshDisplay = 1; char *t1, *t2; t1 = GfTime2Str(car->_lastLapTime, 0); t2 = GfTime2Str(car->_bestLapTime, 0); sprintf(buf,"lap: %02d time: %s best: %s top spd: %.2f min spd: %.2f damage: %d", car->_laps - 1, t1, t2, info->topSpd * 3.6, info->botSpd * 3.6, car->_dammage); ReResScreenAddText(buf); free(t1); free(t2); } /* save the lap result */ ReSavePracticeLap(car); break; case RM_TYPE_QUALIF: if (ReInfo->_displayMode == RM_DISP_MODE_NONE) { ReUpdateQualifCurRes(car); } break; } } else { if ((ReInfo->_displayMode == RM_DISP_MODE_NONE) && (ReInfo->s->_raceType == RM_TYPE_QUALIF)) { ReUpdateQualifCurRes(car); } } info->topSpd = car->_speed_x; info->botSpd = car->_speed_x; if ((car->_remainingLaps < 0) || (s->_raceState == RM_RACE_FINISHING)) { car->_state |= RM_CAR_STATE_FINISH; s->_raceState = RM_RACE_FINISHING; if (ReInfo->s->_raceType == RM_TYPE_RACE) { if (car->_pos == 1) { sprintf(buf, "Winner %s", car->_name); ReRaceBigMsgSet(buf, 10); } else { const char *numSuffix = "th"; if (abs(12 - car->_pos) > 1) { /* leave suffix as 'th' for 11 to 13 */ switch (car->_pos % 10) { case 1: numSuffix = "st"; break; case 2: numSuffix = "nd"; break; case 3: numSuffix = "rd"; break; default: break; } } sprintf(buf, "%s Finished %d%s", car->_name, car->_pos, numSuffix); ReRaceMsgSet(buf, 5); } } } } else { /* prevent infinite looping of cars around track, allow one lap after finish for the first car */ for (i = 0; i < s->_ncars; i++) { s->cars[i]->_state |= RM_CAR_STATE_FINISH; } return; } } else { info->lapFlag--; } } if ((info->prevTrkPos.seg->raceInfo & TR_START) && (car->_trkPos.seg->raceInfo & TR_LAST)) { /* going backward through the start line */ info->lapFlag++; } } ReRaceRules(car); info->prevTrkPos = car->_trkPos; car->_curLapTime = s->currentTime - info->sTime; car->_distFromStartLine = car->_trkPos.seg->lgfromstart + (car->_trkPos.seg->type == TR_STR ? car->_trkPos.toStart : car->_trkPos.toStart * car->_trkPos.seg->radius); car->_distRaced = (car->_laps - 1) * ReInfo->track->length + car->_distFromStartLine; }
void ReSituationUpdater::runOneStep(double deltaTimeIncrement) { tRmInfo* pCurrReInfo = ReSituation::self().data(); tSituation *s = pCurrReInfo->s; // Race messages life cycle management. ReRaceMsgManage(pCurrReInfo); if (NetGetNetwork()) { // Resync clock in case computer falls behind if (s->currentTime < 0.0) { s->currentTime = GfTimeClock() - NetGetNetwork()->GetRaceStartTime(); } if (s->currentTime < -2.0) { std::ostringstream ossMsg; ossMsg << "Race will start in " << -(int)s->currentTime << " seconds"; ReRaceMsgSetBig(pCurrReInfo, ossMsg.str().c_str()); } } //GfLogDebug("ReSituationUpdater::runOneStep: currTime=%.3f\n", s->currentTime); if (s->currentTime >= -2.0 && s->currentTime < deltaTimeIncrement - 2.0) { ReRaceMsgSetBig(pCurrReInfo, "Ready", 1.0); GfLogInfo("Ready.\n"); } else if (s->currentTime >= -1.0 && s->currentTime < deltaTimeIncrement - 1.0) { ReRaceMsgSetBig(pCurrReInfo, "Set", 1.0); GfLogInfo("Set.\n"); } else if (s->currentTime >= 0.0 && s->currentTime < deltaTimeIncrement) { ReRaceMsgSetBig(pCurrReInfo, "Go", 1.0); GfLogInfo("Go.\n"); } // Update times. pCurrReInfo->_reCurTime += deltaTimeIncrement * pCurrReInfo->_reTimeMult; /* "Real" time */ s->currentTime += deltaTimeIncrement; /* Simulated time */ if (s->currentTime < 0) { /* no simu yet */ pCurrReInfo->s->_raceState = RM_RACE_PRESTART; } else if (pCurrReInfo->s->_raceState == RM_RACE_PRESTART) { pCurrReInfo->s->_raceState = RM_RACE_RUNNING; s->currentTime = 0.0; /* resynchronize */ pCurrReInfo->_reLastRobTime = 0.0; } tTrackLocalInfo *trackLocal = &ReInfo->track->local; if (s->currentTime > 0 && trackLocal->timeofdayindex == 9) { //RM_VAL_TIME_24HR if (s->_totTime > 0) { // Scaled on Total Time s->accelTime = 24 * 3600 * s->currentTime / s->_totTime; } else { // Scaled on Number of Laps that the lead driver has completed if (s->cars[0]->_laps > 0 && s->cars[0]->_laps <= s->_totLaps) { // prevent issues if lead driver crosses line the wrong way if (pCurrReInfo->raceEngineInfo.carInfo->lapFlag) s->accelTime = s->cars[0]->_laps - 1; else s->accelTime = s->cars[0]->_laps - 1 + (s->cars[0]->_distFromStartLine / pCurrReInfo->track->length); s->accelTime = 24 * 3600 * s->accelTime / s->_totLaps; } else s->accelTime = 0; } } else s->accelTime = s->currentTime; GfProfStartProfile("rbDrive*"); GfSchedBeginEvent("raceupdate", "robots"); if ((s->currentTime - pCurrReInfo->_reLastRobTime) >= RCM_MAX_DT_ROBOTS) { s->deltaTime = s->currentTime - pCurrReInfo->_reLastRobTime; tRobotItf *robot; for (int i = 0; i < s->_ncars; i++) { if ((s->cars[i]->_state & RM_CAR_STATE_NO_SIMU) == 0) { robot = s->cars[i]->robot; robot->rbDrive(robot->index, s->cars[i], s); } else if (! (s->cars[i]->_state & RM_CAR_STATE_ENDRACE_CALLED ) && ( s->cars[i]->_state & RM_CAR_STATE_OUT ) == RM_CAR_STATE_OUT ) { // No simu, look if it is out robot = s->cars[i]->robot; if (robot->rbEndRace) robot->rbEndRace(robot->index, s->cars[i], s); s->cars[i]->_state |= RM_CAR_STATE_ENDRACE_CALLED; } } pCurrReInfo->_reLastRobTime = s->currentTime; } GfSchedEndEvent("raceupdate", "robots"); GfProfStopProfile("rbDrive*"); if (NetGetNetwork()) ReNetworkOneStep(); GfProfStartProfile("physicsEngine.update*"); GfSchedBeginEvent("raceupdate", "physics"); RePhysicsEngine().updateSituation(s, deltaTimeIncrement); bool bestLapChanged = false; for (int i = 0; i < s->_ncars; i++) ReCarsManageCar(s->cars[i], bestLapChanged); GfSchedEndEvent("raceupdate", "physics"); GfProfStopProfile("physicsEngine.update*"); ReCarsSortCars(); // Update results if a best lap changed if (pCurrReInfo->_displayMode == RM_DISP_MODE_NONE && s->_ncars > 1 && bestLapChanged) { if (pCurrReInfo->s->_raceType == RM_TYPE_PRACTICE) ReUpdatePracticeCurRes(pCurrReInfo->s->cars[0]); else if (pCurrReInfo->s->_raceType == RM_TYPE_QUALIF) ReUpdateQualifCurRes(pCurrReInfo->s->cars[0]); } }
/* return state mode */ static int reRaceRealStart(void) { int i, j; int sw, sh, vw, vh; tRobotItf *robot; tReCarInfo *carInfo; const int BUFSIZE = 1024; char buf[BUFSIZE]; int foundHuman; void *params = ReInfo->params; void *results = ReInfo->results; tSituation *s = ReInfo->s; RmLoadingScreenSetText("Loading Simulation Engine..."); const char* dllname = GfParmGetStr(ReInfo->_reParam, "Modules", "simu", ""); snprintf(buf, BUFSIZE, "%smodules/simu/%s.%s", GetLibDir (), dllname, DLLEXT); if (GfModLoad(0, buf, &ReRaceModList)) return RM_QUIT; ReRaceModList->modInfo->fctInit(ReRaceModList->modInfo->index, &ReInfo->_reSimItf); if (ReInitCars()) { return RM_QUIT; } /* Blind mode or not */ if (ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) { 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++) { snprintf(buf, BUFSIZE, "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_NONE) { if (ReInfo->s->_raceType == RM_TYPE_QUALIF) { ReUpdateQualifCurRes(s->cars[0]); } else { snprintf(buf, BUFSIZE, "%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; if ((ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) && ReInfo->_reGraphicItf.initview != 0) { 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..."); */ stopMenuMusic(); ReInfo->_reGraphicItf.initcars(s); } GfuiScreenActivate(ReInfo->_reGameScreen); } // If the race is adaptive, initialize performance measurement. Uses strategy pattern, pass in the desired performance measurement object. if (taManager->IsActive()) { if (taManager->GetRaceType() == torcsAdaptive::TARaceType::Adaptive) taManager->InitPerfMeasurement(new RaceLineEvaluation(&ReInfo->carList[0], Pathfinder::K1999, ReInfo->track, ReInfo->s)); } return RM_SYNC | RM_NEXT_STEP; }