Re #330 (Task D16 : Complete the new Career racing mode for 2.0) Added a race-type-customizable filtering system for the car categories and driver types + applied it to all race types + added better (but still not correct) support for the Career mode in the Raceman menu

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@3331 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: faba08d04daad7b5bfaa8deab8f735aefcc63779
Former-commit-id: bd867efff6a2ee8ee71ed48966c6684b8834a749
This commit is contained in:
pouillot 2011-02-06 21:55:37 +00:00
parent 76280fb323
commit 90e565f811
17 changed files with 453 additions and 145 deletions

View file

@ -264,6 +264,13 @@ typedef struct RmInfo
#define RM_ATTR_MAXNUM "maximum number"
#define RM_ATTR_MINNUM "minimum number"
#define RM_ATTR_FOCUSED "focused module"
#define RM_ATTR_FOCUSEDIDX "focused idx"
#define RM_ATTR_ACCEPT_TYPES "accepted types"
#define RM_ATTR_REJECT_TYPES "rejected types"
#define RM_ATTR_ACCEPT_CATEGORIES "accepted categories"
#define RM_ATTR_REJECT_CATEGORIES "rejected categories"
#define RM_ATTR_TOTALNUM "total number"
#define RM_ATTR_MAX_DRV "maximum drivers"
#define RM_ATTR_NUMBER "number"
@ -290,8 +297,6 @@ typedef struct RmInfo
#define RM_ATTR_SKINTARGETS "skin targets"
#define RM_ATTR_EXTENDED "extended"
#define RM_ATTR_SKILLLEVEL "skill level"
#define RM_ATTR_FOCUSED "focused module"
#define RM_ATTR_FOCUSEDIDX "focused idx"
#define RM_ATTR_DISPMODE "display mode"
#define RM_ATTR_DISPRES "display results"

View file

@ -122,7 +122,8 @@ rmdsHighlightDriver(const GfDriver* pDriver)
{
if (pCompetitor == pDriver)
{
//GfLogDebug("Selecting competitor #%d '%s'\n", curDrvIndex, pCompetitor->getName().c_str());
//GfLogDebug("Highlighting competitor #%d '%s'\n",
// curDrvIndex, pCompetitor->getName().c_str());
GfuiScrollListSetSelectedElement(ScrHandle, CompetitorsScrollListId, index);
rmdsClickOnDriver(0);
return;
@ -137,7 +138,7 @@ rmdsHighlightDriver(const GfDriver* pDriver)
{
if (pCandidate == pDriver)
{
//GfLogDebug("Selecting candidate #%d '%s'\n", curDrvIndex, name);
//GfLogDebug("Highlighting candidate #%d '%s'\n", curDrvIndex, name);
GfuiScrollListSetSelectedElement(ScrHandle, CandidatesScrollListId, index);
rmdsClickOnDriver(0);
return;
@ -169,22 +170,32 @@ rmdsActivate(void * /* notused */)
// Update GUI : current driver info, car preview.
rmdsHighlightDriver(PCurrentDriver);
// Initialize the driver type filter criteria to "any driver".
CurDriverTypeIndex =
(std::find(VecDriverTypes.begin(), VecDriverTypes.end(), AnyDriverType)
- VecDriverTypes.begin()) % VecDriverTypes.size();
// Initialize the driver type filter criteria to "any driver" if possible.
// or else the first available type.
const std::vector<std::string>::const_iterator itDrvTyp =
std::find(VecDriverTypes.begin(), VecDriverTypes.end(), AnyDriverType);
if (itDrvTyp == VecDriverTypes.end())
CurDriverTypeIndex = 0;
else
CurDriverTypeIndex = itDrvTyp - VecDriverTypes.begin();
// Initialize the car category filter criteria : use the one of the current driver if any.
const std::string strCurCarCatId =
// Initialize the car category filter criteria :
// use the one of the current driver if any, or else "any category" if possible,
// or else the first available category.
const std::string strCarCatId =
PCurrentDriver ? PCurrentDriver->getCar()->getCategoryId() : AnyCarCategory;
CurCarCategoryIndex =
(std::find(VecCarCategoryIds.begin(), VecCarCategoryIds.end(), strCurCarCatId)
- VecCarCategoryIds.begin()) % VecCarCategoryIds.size();
const std::vector<std::string>::const_iterator itCarCat =
std::find(VecCarCategoryIds.begin(), VecCarCategoryIds.end(), strCarCatId);
if (itCarCat == VecCarCategoryIds.end())
CurCarCategoryIndex = 0;
else
CurCarCategoryIndex = itCarCat - VecCarCategoryIds.begin();
// Update GUI (candidate list, filter criteria).
GfuiLabelSetText(ScrHandle, DriverTypeEditId, VecDriverTypes[CurDriverTypeIndex].c_str());
GfuiLabelSetText(ScrHandle, CarCategoryEditId, VecCarCategoryNames[CurCarCategoryIndex].c_str());
rmdsFilterCandidatesScrollList(strCurCarCatId, VecDriverTypes[CurDriverTypeIndex]);
rmdsFilterCandidatesScrollList(VecCarCategoryIds[CurCarCategoryIndex],
VecDriverTypes[CurDriverTypeIndex]);
}
static void
@ -216,7 +227,7 @@ rmdsChangeCarCategory(void *vp)
GfuiLabelSetText(ScrHandle, CarCategoryEditId, VecCarCategoryNames[CurCarCategoryIndex].c_str());
rmdsFilterCandidatesScrollList(VecCarCategoryIds[CurCarCategoryIndex],
VecDriverTypes[CurDriverTypeIndex]);
VecDriverTypes[CurDriverTypeIndex]);
if (rmdsIsAnyCompetitorHighlighted())
GfuiEnable(ScrHandle, ChangeCarButtonId, GFUI_ENABLE);
@ -231,7 +242,7 @@ rmdsChangeDriverType(void *vp)
GfuiLabelSetText(ScrHandle, DriverTypeEditId, VecDriverTypes[CurDriverTypeIndex].c_str());
rmdsFilterCandidatesScrollList(VecCarCategoryIds[CurCarCategoryIndex],
VecDriverTypes[CurDriverTypeIndex]);
VecDriverTypes[CurDriverTypeIndex]);
if (rmdsIsAnyCompetitorHighlighted())
GfuiEnable(ScrHandle, ChangeCarButtonId, GFUI_ENABLE);
@ -403,12 +414,34 @@ rmdsSelectDeselectDriver(void * /* dummy */ )
// and add him to the Competitors scroll-list and to the race competitors.
bSelect = false;
name = 0;
if (MenuData->pRace->acceptsMoreCompetitors()) {
if (MenuData->pRace->acceptsMoreCompetitors())
{
src = CandidatesScrollListId;
name = GfuiScrollListExtractSelectedElement(ScrHandle, src, (void**)&pDriver);
if (name) {
if (name)
{
dst = CompetitorsScrollListId;
GfuiScrollListInsertElement(ScrHandle, dst, name, GfDrivers::self()->getCount(), (void*)pDriver);
// Change human car to an accepted category if this not the case, and if possible.
if (pDriver->isHuman()
&& !MenuData->pRace->acceptsCarCategory(pDriver->getCar()->getCategoryId()))
{
const std::vector<std::string>& vecAccCatIds =
MenuData->pRace->getAcceptedCarCategoryIds();
if (vecAccCatIds.size() > 0)
{
const GfCar* pNewCar = GfCars::self()->getCarsInCategory(vecAccCatIds[0])[0];
if (pNewCar)
{
const GfCar* pOldCar = pDriver->getCar();
pDriver->setCar(pNewCar);
GfLogTrace("Changing %s car to %s (%s category was not accepted)\n",
pDriver->getName().c_str(), pNewCar->getName().c_str(),
pOldCar->getName().c_str());
}
}
}
MenuData->pRace->appendCompetitor(pDriver); // Now selected.
}
}
@ -416,27 +449,29 @@ rmdsSelectDeselectDriver(void * /* dummy */ )
// Otherwise, if the selected driver is in the Competitors scroll-list,
// remove the driver from the Competitors scroll-list and from the race competitors,
// and add him to the Candidate scroll-list
// (if it matches the Candidate scroll-list filtering criteria)
if (!name) {
// (if it matches the Candidate scroll-list filtering criteria,
// see rmdsFilterCandidatesScrollList for how humans enjoy a different filtering).
if (!name)
{
bSelect = true;
src = CompetitorsScrollListId;
name = GfuiScrollListExtractSelectedElement(ScrHandle, src, (void**)&pDriver);
if (name) {
const std::string strCarCatIdFilter =
(VecCarCategoryIds[CurCarCategoryIndex] == AnyCarCategory
? "" : VecCarCategoryIds[CurCarCategoryIndex]);
const std::string strTypeFilter =
(VecDriverTypes[CurDriverTypeIndex] == AnyDriverType
? "" : VecDriverTypes[CurDriverTypeIndex]);
if (pDriver->matchesTypeAndCategory(strTypeFilter, strCarCatIdFilter)) {
dst = CandidatesScrollListId;
GfuiScrollListInsertElement(ScrHandle, dst, name,
pDriver->isHuman() ? 0 : GfDrivers::self()->getCount(), (void*)pDriver);
}
MenuData->pRace->removeCompetitor(pDriver); // No more selected.
} else {
return;
if (!name)
return; // Should never happen.
const std::string strCarCatIdFilter =
(pDriver->isHuman() || VecCarCategoryIds[CurCarCategoryIndex] == AnyCarCategory
? "" : VecCarCategoryIds[CurCarCategoryIndex]);
const std::string strTypeFilter =
(VecDriverTypes[CurDriverTypeIndex] == AnyDriverType
? "" : VecDriverTypes[CurDriverTypeIndex]);
if (pDriver->matchesTypeAndCategory(strTypeFilter, strCarCatIdFilter))
{
dst = CandidatesScrollListId;
GfuiScrollListInsertElement(ScrHandle, dst, name,
pDriver->isHuman() ? 0 : GfDrivers::self()->getCount(), (void*)pDriver);
}
MenuData->pRace->removeCompetitor(pDriver); // No more selected.
}
// Focused driver management (inhibited for the moment : what is it useful for ?)
@ -572,13 +607,21 @@ RmDriversSelect(void *vs)
// Car category filtering "combobox" (left arrow, label, right arrow)
CreateButtonControl(ScrHandle, menuDescHdle, "carcategoryleftarrow", (void*)-1, rmdsChangeCarCategory);
CreateButtonControl(ScrHandle, menuDescHdle, "carcategoryrightarrow", (void*)1, rmdsChangeCarCategory);
const int nCatPrevButtonId =
CreateButtonControl(ScrHandle, menuDescHdle, "carcategoryleftarrow",
(void*)-1, rmdsChangeCarCategory);
const int nCatNextButtonId =
CreateButtonControl(ScrHandle, menuDescHdle, "carcategoryrightarrow",
(void*)1, rmdsChangeCarCategory);
CarCategoryEditId = CreateLabelControl(ScrHandle, menuDescHdle, "carcategorytext");
// Driver type filtering "combobox" (left arrow, label, right arrow)
CreateButtonControl(ScrHandle, menuDescHdle, "drivertypeleftarrow", (void*)-1, rmdsChangeDriverType);
CreateButtonControl(ScrHandle, menuDescHdle, "drivertyperightarrow", (void*)1, rmdsChangeDriverType);
const int nDrvTypPrevButtonId =
CreateButtonControl(ScrHandle, menuDescHdle, "drivertypeleftarrow",
(void*)-1, rmdsChangeDriverType);
const int nDrvTypNextButtonId =
CreateButtonControl(ScrHandle, menuDescHdle, "drivertyperightarrow",
(void*)1, rmdsChangeDriverType);
DriverTypeEditId = CreateLabelControl(ScrHandle, menuDescHdle, "drivertypetext");
// Scroll-lists manipulation buttons
@ -600,22 +643,47 @@ RmDriversSelect(void *vs)
CarImageId = CreateStaticImageControl(ScrHandle, menuDescHdle, "carpreviewimage");
GfuiStaticImageSet(ScrHandle, CarImageId, "data/img/nocarpreview.png");
// Initialize the car category Ids, names and driver types lists for the driver filter system.
VecCarCategoryIds = GfCars::self()->getCategoryIds();
VecCarCategoryIds.push_back(AnyCarCategory);
VecCarCategoryNames = GfCars::self()->getCategoryNames();
VecCarCategoryNames.push_back(AnyCarCategory);
// Initialize the car category Ids and names for the driver filter system.
for (unsigned nCatInd = 0; nCatInd < GfCars::self()->getCategoryIds().size(); nCatInd++)
{
// Keep only accepted categories.
if (MenuData->pRace->acceptsCarCategory(GfCars::self()->getCategoryIds()[nCatInd]))
{
VecCarCategoryIds.push_back(GfCars::self()->getCategoryIds()[nCatInd]);
VecCarCategoryNames.push_back(GfCars::self()->getCategoryNames()[nCatInd]);
//GfLogDebug("Accepted cat : %s\n", GfCars::self()->getCategoryIds()[nCatInd].c_str());
}
}
if (VecDriverTypes.size() > 1)
{
VecCarCategoryIds.push_back(AnyCarCategory);
VecCarCategoryNames.push_back(AnyCarCategory);
}
else
{
GfuiEnable(ScrHandle, nCatPrevButtonId, GFUI_DISABLE);
GfuiEnable(ScrHandle, nCatNextButtonId, GFUI_DISABLE);
}
// Initialize the driver types lists for the driver filter system.
std::vector<std::string>::const_iterator itDrvType = GfDrivers::self()->getTypes().begin();
while (itDrvType != GfDrivers::self()->getTypes().end())
{
// No network human in non network races.
if (*itDrvType != "networkhuman" || MenuData->pRace->getManager()->isNetwork())
// Keep only accepted types.
if (MenuData->pRace->acceptsDriverType(*itDrvType))
{
VecDriverTypes.push_back(*itDrvType);
//GfLogDebug("Accepted type : %s\n", itDrvType->c_str());
}
itDrvType++;
}
VecDriverTypes.push_back(AnyDriverType);
if (VecDriverTypes.size() > 1)
VecDriverTypes.push_back(AnyDriverType);
else
{
GfuiEnable(ScrHandle, nDrvTypPrevButtonId, GFUI_DISABLE);
GfuiEnable(ScrHandle, nDrvTypNextButtonId, GFUI_DISABLE);
}
// Current Driver Info
CurrentDriverTypeLabelId =
@ -660,28 +728,52 @@ RmDriversSelect(void *vs)
static void
rmdsFilterCandidatesScrollList(const std::string& strCarCatId, const std::string& strType)
{
// Empty the unselected scroll-list
// Empty the unselected scroll-list
GfuiScrollListClear(ScrHandle, CandidatesScrollListId);
GfuiEnable(ScrHandle, SelectButtonId, GFUI_DISABLE);
// Fill it with drivers that match the filter criteria and are not among competitors.
// Fill it with drivers that match the filter criteria,
// are accepted by the race and are not already among competitors.
// Note: We must check this race acceptance because strCarCatId and strType may be empty,
// and in these cases getDriversWithTypeAndCategory(...) filters less.
// a) Retrieve the list of competitors.
const std::vector<GfDriver*>& vecCompetitors = MenuData->pRace->getCompetitors();
const std::string strCarCatIdFilter = (strCarCatId == AnyCarCategory ? "" : strCarCatId);
const std::string strTypeFilter = (strType == AnyDriverType ? "" : strType);
// b) Tweak the filtering criteria :
// - use "" for AnyCarCategory,
// - use "" for AnyDriverType,
// - when strType is "*human", set strCarCatId to AnyCarCategory
// (because humans can change their car for the race, and so they have
// to be in the candidate list even if their current car is not in the right category).
const std::string strCarCatIdFilter =
(strCarCatId == AnyCarCategory || strType.find("human") != strType.npos)
? "" : strCarCatId;
const std::string strTypeFilter = strType == AnyDriverType ? "" : strType;
// c) Retrieve the list of drivers matching with the criteria.
const std::vector<GfDriver*> vecCandidates =
GfDrivers::self()->getDriversWithTypeAndCategory(strTypeFilter, strCarCatIdFilter);
//GfLogDebug("rmdsFilterCandidatesScrollList('%s' => '%s', '%s' => '%s')\n",
// strCarCatId.c_str(), strCarCatIdFilter.c_str(),
// strType.c_str(), strTypeFilter.c_str());
// e) Keep only drivers accepted by the race and not already among competitors
// (but don't reject humans with the wrong car category : they must be able to change it).
std::vector<GfDriver*>::const_iterator itCandidate;
int index = 1;
for (itCandidate = vecCandidates.begin(); itCandidate != vecCandidates.end(); itCandidate++)
{
if (std::find(vecCompetitors.begin(), vecCompetitors.end(), *itCandidate)
== vecCompetitors.end())
== vecCompetitors.end()
&& MenuData->pRace->acceptsDriverType((*itCandidate)->getType())
&& ((*itCandidate)->isHuman()
|| MenuData->pRace->acceptsCarCategory((*itCandidate)->getCar()->getCategoryId())))
GfuiScrollListInsertElement(ScrHandle, CandidatesScrollListId,
(*itCandidate)->getName().c_str(), index++,
(*itCandidate)->getName().c_str(), // Item string
itCandidate - vecCandidates.begin() + 1, // Insert. index
(void*)(*itCandidate));
}
// Show first element if any
// Show first element of the list if any.
GfuiScrollListShowElement(ScrHandle, CandidatesScrollListId, 0);
}

View file

@ -40,7 +40,8 @@ static const char *TimeOfDaySpecNames[GfRace::nTimeSpecNumber] = RM_VALS_TIME;
static const char* CloudsSpecNames[GfRace::nCloudsSpecNumber] = RM_VALS_CLOUDS;
static const char *RainSpecNames[GfRace::nRainSpecNumber] = RM_VALS_RAIN;
// Private data for GfRace
// Private data for GfRace
class GfRace::Private
{
public:
@ -71,8 +72,15 @@ public:
// Focused competitor (what for ?).
std::string strFocusedModuleName;
int nFocusedItfIndex;
// An empty string vector.
static const std::vector<std::string> vecstrEmpty;
};
const std::vector<std::string> GfRace::Private::vecstrEmpty;
// GfRace class.
GfRace::GfRace()
{
_pPrivate = new GfRace::Private;
@ -199,14 +207,6 @@ void GfRace::load(GfRaceManager* pRaceMan)
continue;
}
// Check if this driver can compete in this race.
if (pCompetitor->isNetwork() && !pRaceMan->isNetwork())
{
GfLogWarning("Ignoring '%s' driver #%d (%s) : Network humans can only race in network races\n",
pszModName, nItfIndex, pCompetitor->getName().c_str());
continue;
}
// We've got it : if we can keep it for the race, make it a competitor
// (there is a threshold on the number of competitors) :
if (acceptsMoreCompetitors())
@ -220,7 +220,7 @@ void GfRace::load(GfRaceManager* pRaceMan)
? true : false;
// Get the chosen car for the race if any specified (human only).
const GfCar* pCar = 0;
const GfCar* pCarForRace = 0;
if (pCompetitor->isHuman() && bExtended)
{
ossDrvSecPath.str("");
@ -228,23 +228,35 @@ void GfRace::load(GfRaceManager* pRaceMan)
<< '/' << (bExtended ? 1 : 0) << '/' << nItfIndex;
const char* pszCarId =
GfParmGetStr(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_CARNAME, 0);
pCar = GfCars::self()->getCar(pszCarId);
if (!pCar)
pCarForRace = GfCars::self()->getCar(pszCarId);
if (!pCarForRace)
{
GfLogError("Falling back to default car '%s' "
"for %s because '%s' is not available\n",
pCompetitor->getCar()->getName().c_str(),
pCompetitor->getName().c_str(), pszCarId);
pCompetitor->getCar()->getName().c_str(), pszCarId);
}
}
// Update the driver.
GfDriverSkin skin(pszSkinName);
skin.setTargets(nSkinTargets);
pCompetitor->setSkin(skin);
if (pCar) // Override default car.
pCompetitor->setCar(pCar);
if (pCarForRace) // Override default car with the one chosen for the race if any.
pCompetitor->setCar(pCarForRace);
// Update the GfRace.
appendCompetitor(pCompetitor);
// Check if this driver can compete in this race.
if (acceptsDriverType(pCompetitor->getType())
&& acceptsCarCategory(pCompetitor->getCar()->getCategoryId()))
{
// Update the GfRace.
appendCompetitor(pCompetitor);
}
else
{
GfLogWarning("Ignoring '%s' (%s' #%d) : Type or car category not accepted by the race\n",
pCompetitor->getName().c_str(), pszModName, nItfIndex);
}
}
else
{
@ -398,6 +410,28 @@ int GfRace::getSupportedFeatures() const
return nFeatures;
}
bool GfRace::acceptsDriverType(const std::string& strType) const
{
return _pPrivate->pRaceMan ? _pPrivate->pRaceMan->acceptsDriverType(strType) : false;
}
const std::vector<std::string>& GfRace::getAcceptedDriverTypes() const
{
return _pPrivate->pRaceMan
? _pPrivate->pRaceMan->getAcceptedDriverTypes() : _pPrivate->vecstrEmpty;
}
bool GfRace::acceptsCarCategory(const std::string& strCatId) const
{
return _pPrivate->pRaceMan ? _pPrivate->pRaceMan->acceptsCarCategory(strCatId) : false;
}
const std::vector<std::string>& GfRace::getAcceptedCarCategoryIds() const
{
return _pPrivate->pRaceMan
? _pPrivate->pRaceMan->getAcceptedCarCategoryIds() : _pPrivate->vecstrEmpty;
}
const std::vector<GfDriver*>& GfRace::getCompetitors() const
{
return _pPrivate->vecCompetitors;

View file

@ -81,6 +81,11 @@ public:
Parameters* getParameters();
int getSupportedFeatures() const;
bool acceptsDriverType(const std::string& strType) const;
const std::vector<std::string>& getAcceptedDriverTypes() const;
bool acceptsCarCategory(const std::string& strCatId) const;
const std::vector<std::string>& getAcceptedCarCategoryIds() const;
unsigned getCompetitorsCount() const;
const std::vector<GfDriver*>& getCompetitors() const;

View file

@ -23,7 +23,9 @@
#include <raceman.h>
#include "cars.h"
#include "tracks.h"
#include "drivers.h"
#include "racemanagers.h"
@ -110,6 +112,7 @@ GfRaceManagers::GfRaceManagers()
}
// Create the race manager and load it from the params file.
GfLogDebug("GfRaceManagers::GfRaceManagers: creating '%s'\n", strRaceManId.c_str());
GfRaceManager* pRaceMan = new GfRaceManager(strRaceManId, hparmRaceMan);
// Update the GfRaceManagers singleton.
@ -181,9 +184,11 @@ void GfRaceManagers::print() const
getRaceManagersWithType(itType->c_str());
std::vector<GfRaceManager*>::const_iterator itRaceMan;
for (itRaceMan = vecRaceMans.begin(); itRaceMan != vecRaceMans.end(); itRaceMan++)
{
GfLogTrace(" %s : subtype='%s', name='%s', events=%d\n",
(*itRaceMan)->getId().c_str(), (*itRaceMan)->getSubType().c_str(),
(*itRaceMan)->getName().c_str(), (*itRaceMan)->getEventCount());
}
}
}
@ -194,11 +199,76 @@ GfRaceManager::GfRaceManager(const std::string& strId, void* hparmHandle)
_strId = strId;
// Load constant properties (never changed afterwards).
// 1) Name, type, sub-type and priority (ordering the buttons in the race select menu).
_strName = GfParmGetStr(hparmHandle, RM_SECT_HEADER, RM_ATTR_NAME, "<unknown>");
_strType = GfParmGetStr(hparmHandle, RM_SECT_HEADER, RM_ATTR_TYPE, "<unknown>");
_strSubType = GfParmGetStr(hparmHandle, RM_SECT_HEADER, RM_ATTR_SUBTYPE, "");
_nPriority = (int)GfParmGetNum(hparmHandle, RM_SECT_HEADER, RM_ATTR_PRIO, NULL, 10000);
// 2) Accepted driver types.
static const char cFilterSeparator = ';';
// a) Load accepted driver types from a ';'-separated string (ignore duplicates).
const char* pszAcceptDrvTypes =
GfParmGetStr(hparmHandle, RM_SECT_DRIVERS, RM_ATTR_ACCEPT_TYPES, "");
std::stringstream ssAcceptDrvTypes(pszAcceptDrvTypes);
std::string strDrvType;
while(std::getline(ssAcceptDrvTypes, strDrvType, cFilterSeparator))
{
std::vector<std::string>::iterator itDrvType =
std::find(_vecAcceptedDriverTypes.begin(), _vecAcceptedDriverTypes.end(), strDrvType);
if (itDrvType == _vecAcceptedDriverTypes.end()) // Not already there => store it.
_vecAcceptedDriverTypes.push_back(strDrvType);
}
// b) If the race file finally doesn't specify any accepted driver type,
// accpet them all.
if (_vecAcceptedDriverTypes.empty())
_vecAcceptedDriverTypes = GfDrivers::self()->getTypes();
// c) Load rejected driver types from a ';'-separated string (ignore duplicates).
const char* pszRejectDrvTypes =
GfParmGetStr(hparmHandle, RM_SECT_DRIVERS, RM_ATTR_REJECT_TYPES, "");
std::stringstream ssRejectDrvTypes(pszRejectDrvTypes);
while(std::getline(ssRejectDrvTypes, strDrvType, cFilterSeparator))
{
std::vector<std::string>::iterator itDrvType =
std::find(_vecAcceptedDriverTypes.begin(), _vecAcceptedDriverTypes.end(), strDrvType);
if (itDrvType != _vecAcceptedDriverTypes.end()) // Accepted til now => now rejected.
_vecAcceptedDriverTypes.erase(itDrvType);
}
// 3) Accepted car categories.
// a) Load accepted car categories from a ';'-separated string (ignore duplicates).
const char* pszAcceptCarCats =
GfParmGetStr(hparmHandle, RM_SECT_DRIVERS, RM_ATTR_ACCEPT_CATEGORIES, "");
std::stringstream ssAcceptCarCats(pszAcceptCarCats);
std::string strCarCat;
while(std::getline(ssAcceptCarCats, strCarCat, cFilterSeparator))
{
std::vector<std::string>::iterator itCarCat =
std::find(_vecAcceptedCarCategoryIds.begin(), _vecAcceptedCarCategoryIds.end(), strCarCat);
if (itCarCat == _vecAcceptedCarCategoryIds.end()) // Not already there => store it.
_vecAcceptedCarCategoryIds.push_back(strCarCat);
}
// b) If the race file finally doesn't specify any accepted car category,
// accpet them all.
if (_vecAcceptedCarCategoryIds.empty())
_vecAcceptedCarCategoryIds = GfCars::self()->getCategoryIds();
// c) Load rejected car categories from a ';'-separated string (ignore duplicates).
const char* pszRejectCarCats =
GfParmGetStr(hparmHandle, RM_SECT_DRIVERS, RM_ATTR_REJECT_CATEGORIES, "");
std::stringstream ssRejectCarCats(pszRejectCarCats);
while(std::getline(ssRejectCarCats, strCarCat, cFilterSeparator))
{
std::vector<std::string>::iterator itCarCat =
std::find(_vecAcceptedCarCategoryIds.begin(), _vecAcceptedCarCategoryIds.end(), strCarCat);
if (itCarCat != _vecAcceptedCarCategoryIds.end()) // Accepted til now => now rejected.
_vecAcceptedCarCategoryIds.erase(itCarCat);
}
// Load other "mutable" properties.
reset(hparmHandle, false);
}
@ -209,11 +279,39 @@ void GfRaceManager::reset(void* hparmHandle, bool bClosePrevHdle)
GfParmReleaseHandle(_hparmHandle);
_hparmHandle = hparmHandle;
// Determine the race manager file from which to load the events info.
// 1) Simple case : the race manager has no subfiles, use the normal file.
// 2) Career case : the events are defined in "sub-championships" files.
// WARNING: Very partial support for the moment : we only care about the 1st event
// ('cause it is quite complicated, with events are intermixed between
// the other "sub-championships", each defined in a career_<sub-champ>.xmls).
// This is not an issue as long as this class is not used in the race engine
// or the event management purpose (everything is in racecareer.cpp for now).
const char* pszHasSubFiles =
GfParmGetStr(_hparmHandle, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO);
_bHasSubFiles = strcmp(pszHasSubFiles, RM_VAL_YES) ? false : true;
if (_bHasSubFiles)
{
const char* psz1stSubFileName =
GfParmGetStr(_hparmHandle, RM_SECT_SUBFILES, RM_ATTR_FIRSTSUBFILE, 0);
if (psz1stSubFileName)
{
std::ostringstream ossSubFilePath;
ossSubFilePath << GfLocalDir() << "config/raceman/" << psz1stSubFileName;
hparmHandle = GfParmReadFile(ossSubFilePath.str().c_str(), GFPARM_RMODE_STD);
}
if (!hparmHandle)
_bHasSubFiles = false;
}
// Get current event in the schedule.
_nCurrentEventInd =
(int)GfParmGetNum(_hparmHandle, RM_SECT_TRACKS, RE_ATTR_CUR_TRACK, NULL, 1) - 1;
(int)GfParmGetNum(hparmHandle, RM_SECT_TRACKS, RE_ATTR_CUR_TRACK, NULL, 1) - 1;
GfLogDebug("GfRaceManager::reset(%s): curEvent = %d (%s)\n",
_strName.c_str(), _nCurrentEventInd, GfParmGetFileName(hparmHandle));
// Load track id for each event in the schedule.
// Load track id for each event in the schedule
// (warning: we don't check here that the tracks exist and are usable).
std::ostringstream ossSectionPath;
int nEventNum = 1;
const char* pszTrackId;
@ -221,10 +319,16 @@ void GfRaceManager::reset(void* hparmHandle, bool bClosePrevHdle)
{
ossSectionPath.str("");
ossSectionPath << RM_SECT_TRACKS << '/' << nEventNum;
pszTrackId = GfParmGetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME, 0);
pszTrackId = GfParmGetStr(hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME, 0);
GfLogDebug("GfRaceManager::reset(%s): event[%d].track = '%s'\n",
_strName.c_str(), nEventNum-1, pszTrackId);
if (pszTrackId)
{
_vecEventTrackIds.push_back(pszTrackId);
if (GfTracks::self()->getTrack(pszTrackId))
_vecEventTrackIds.push_back(pszTrackId);
else
GfLogWarning("Skipping non-existing track '%s' (event #%d) for %s type\n",
pszTrackId, nEventNum, _strName.c_str());
nEventNum++;
}
}
@ -243,16 +347,26 @@ void GfRaceManager::save()
(tdble)(_nCurrentEventInd + 1));
// Info about each event in the schedule.
std::ostringstream ossSectionPath;
for (unsigned nEventInd = 0; nEventInd < _vecEventTrackIds.size(); nEventInd++)
// WARNING: Not supported for Career mode (TODO ?).
if (!_bHasSubFiles)
{
ossSectionPath.str("");
ossSectionPath << RM_SECT_TRACKS << '/' << nEventInd + 1;
GfParmSetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME,
_vecEventTrackIds[nEventInd].c_str());
GfTrack* pTrack = GfTracks::self()->getTrack(_vecEventTrackIds[nEventInd]);
GfParmSetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_CATEGORY,
pTrack->getCategoryId().c_str());
// a) clear the event list.
GfParmListClean(_hparmHandle, RM_SECT_TRACKS);
// b) re-create it from the current event list state (may have changed since loaded).
std::ostringstream ossSectionPath;
for (unsigned nEventInd = 0; nEventInd < _vecEventTrackIds.size(); nEventInd++)
{
GfLogDebug("GfRaceManager::save(%s): event[%u].track = '%s'\n",
_strName.c_str(), nEventInd, _vecEventTrackIds[nEventInd].c_str());
ossSectionPath.str("");
ossSectionPath << RM_SECT_TRACKS << '/' << nEventInd + 1;
GfParmSetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME,
_vecEventTrackIds[nEventInd].c_str());
GfTrack* pTrack = GfTracks::self()->getTrack(_vecEventTrackIds[nEventInd]);
GfParmSetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_CATEGORY,
pTrack->getCategoryId().c_str());
}
}
}
@ -292,14 +406,36 @@ const std::string& GfRaceManager::getSubType() const
return _strSubType;
}
const int GfRaceManager::getPriority() const
{
return _nPriority;
}
bool GfRaceManager::isNetwork() const
{
return _strType == "Online";
}
const int GfRaceManager::getPriority() const
bool GfRaceManager::acceptsDriverType(const std::string& strType) const
{
return _nPriority;
return std::find(_vecAcceptedDriverTypes.begin(), _vecAcceptedDriverTypes.end(), strType)
!= _vecAcceptedDriverTypes.end();
}
const std::vector<std::string>& GfRaceManager::getAcceptedDriverTypes() const
{
return _vecAcceptedDriverTypes;
}
bool GfRaceManager::acceptsCarCategory(const std::string& strCatId) const
{
return std::find(_vecAcceptedCarCategoryIds.begin(), _vecAcceptedCarCategoryIds.end(), strCatId)
!= _vecAcceptedCarCategoryIds.end();
}
const std::vector<std::string>& GfRaceManager::getAcceptedCarCategoryIds() const
{
return _vecAcceptedCarCategoryIds;
}
unsigned GfRaceManager::getEventCount() const

View file

@ -49,9 +49,14 @@ public:
const std::string& getName() const;
const std::string& getType() const;
const std::string& getSubType() const;
bool isNetwork() const;
const int getPriority() const;
bool isNetwork() const;
bool acceptsDriverType(const std::string& strType) const;
const std::vector<std::string>& getAcceptedDriverTypes() const;
bool acceptsCarCategory(const std::string& strCatId) const;
const std::vector<std::string>& getAcceptedCarCategoryIds() const;
unsigned getEventCount() const;
bool stepToNextEvent();
GfTrack* getCurrentEventTrack();
@ -70,6 +75,11 @@ protected:
std::string _strSubType; // User friendly sub-type name (ex: "", Endurance, Challenge, Supercars").
int _nPriority; // Gives the order of the buttons in the race select menu
std::vector<std::string> _vecAcceptedDriverTypes;
std::vector<std::string> _vecAcceptedCarCategoryIds;
bool _bHasSubFiles; // True if multiple configuration files are used (ex: Career mode).
std::vector<std::string> _vecEventTrackIds; // Id of the track for each event.
int _nCurrentEventInd;
};

View file

@ -16,10 +16,11 @@
<!DOCTYPE params SYSTEM "params.dtd">
<params name="Career" version="1.3">
<params name="Career" version="1.4">
<section name="Header">
<attstr name="name" val="Career"/>
<attstr name="type" val="Career"/>
<attstr name="subtype" val="Standard"/>
<attstr name="description" val="Career"/>
<attnum name="priority" val="30"/>
<attstr name="menu image" val="data/img/splash-career.jpg"/>
@ -166,9 +167,12 @@
</section>
<section name="Drivers">
<attnum name="maximum number" val="50"/>
<attstr name="focused module" val="simplix"/>
<attnum name="focused idx" val="2"/>
<attstr name="accepted types" val="human"/>
<section name="1">
<attnum name="idx" val="1"/>
<attstr name="module" val="human"/>
@ -176,17 +180,17 @@
<section name="2">
<attnum name="idx" val="2"/>
<attstr name="module" val="simplix"/>
<attstr name="module" val="simplix_sc"/>
</section>
<section name="3">
<attnum name="idx" val="3"/>
<attstr name="module" val="simplix"/>
<attstr name="module" val="simplix_sc"/>
</section>
<section name="4">
<attnum name="idx" val="4"/>
<attstr name="module" val="simplix"/>
<attstr name="module" val="simplix_sc"/>
</section>
</section>

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "../libs/tgf/params.dtd">
<params name="LS1 Championship" type="param" mode="mw" version="1.3">
<params name="LS1 Championship" type="param" mode="mw" version="1.4">
<section name="Header">
<attstr name="name" val="LS1 Championship"/>
@ -73,7 +73,7 @@
<attstr name="category" val="road"/>
</section>
<section name="5">
<attstr name="name" val="wheel-2"/>
<attstr name="name" val="karwada"/>
<attstr name="category" val="circuit"/>
</section>
<section name="6">
@ -373,50 +373,50 @@
<section name="1">
<attnum name="idx" val="0"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt I"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix I"/>
<attstr name="car name" val="ls1-vulture-v6r" />
</section>
<section name="2">
<attnum name="idx" val="1"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_ls1"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt II"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix II"/>
<attstr name="car name" val="ls1-vulture-v6r" />
</section>
<section name="3">
<attnum name="idx" val="2"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_ls1"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt III"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix III"/>
<attstr name="car name" val="ls1-vulture-v6r" />
</section>
<section name="4">
<attnum name="idx" val="3"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_ls1"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt IV"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix IV"/>
<attstr name="car name" val="ls1-vulture-v6r" />
</section>
<section name="5">
<attnum name="idx" val="4"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_ls1"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt V"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix V"/>
<attstr name="car name" val="ls1-vulture-v6r" />
</section>
<section name="6">
<attnum name="idx" val="5"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_ls1"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt VI"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix VI"/>
<attstr name="car name" val="ls1-vulture-v6r" />
</section>
</section>

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "../libs/tgf/params.dtd">
<params name="Supercars Championship %A" type="param" mode="mw" version="1.2">
<params name="Supercars Championship %A" type="param" mode="mw" version="1.3">
<section name="Header">
<attform name="name" val="#Supercars Championship # + toAlpha(number)"/>
@ -373,50 +373,50 @@
<section name="1">
<attnum name="idx" val="0"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_sc"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt I"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix I"/>
<attstr name="car name" val="sc-boxer-96" />
</section>
<section name="2">
<attnum name="idx" val="1"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_sc"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt II"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix II"/>
<attstr name="car name" val="sc-boxer-96" />
</section>
<section name="3">
<attnum name="idx" val="2"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_sc"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt III"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix III"/>
<attstr name="car name" val="sc-boxer-96" />
</section>
<section name="4">
<attnum name="idx" val="3"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_sc"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt IV"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix IV"/>
<attstr name="car name" val="sc-boxer-96" />
</section>
<section name="5">
<attnum name="idx" val="4"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_sc"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt V"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix V"/>
<attstr name="car name" val="sc-boxer-96" />
</section>
<section name="6">
<attnum name="idx" val="5"/>
<attstr name="module" val="bt"/>
<attstr name="module" val="simplix_sc"/>
<attnum name="extended" val="1"/>
<attstr name="name" val="bt VI"/>
<attstr name="car name" val="clkdtm" />
<attstr name="name" val="simplix VI"/>
<attstr name="car name" val="sc-boxer-96" />
</section>
</section>

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "params.dtd">
<params name="MPA1 Championship" version="1.5">
<params name="MPA1 Championship" version="1.6">
<section name="Header">
<attstr name="name" val="MPA1 Championship"/>
@ -233,9 +233,13 @@
</section>
<section name="Drivers">
<attnum name="maximum number" val="50"/>
<attnum name="focused idx" val="0"/>
<attstr name="focused module" val="simplix_mpa1"/>
<attstr name="rejected types" val="networkhuman"/>
<attstr name="accepted categories" val="MPA1"/>
<section name="1">
<attnum name="idx" val="0"/>
<attstr name="module" val="simplix_mpa1"/>

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "params.dtd">
<params name="Supercar Championship" version="1.3">
<params name="Supercar Championship" version="1.4">
<section name="Header">
<attstr name="name" val="Supercar Championship"/>
<attstr name="type" val="Championship"/>
@ -45,7 +45,7 @@
</section>
<section name="4">
<attstr name="name" val="g-track-2"/>
<attstr name="name" val="chemisay"/>
<attstr name="category" val="circuit"/>
</section>
@ -217,7 +217,12 @@
</section>
<section name="Drivers">
<attnum name="maximum number" val="50"/>
<attnum name="focused idx" val="1"/>
<attstr name="focused module" val="usr_sc"/>
<attstr name="rejected types" val="networkhuman"/>
<attstr name="accepted categories" val="Supercars"/>
<section name="1">
<attnum name="idx" val="1"/>

View file

@ -16,7 +16,7 @@
<!DOCTYPE params SYSTEM "params.dtd">
<params name="Championship" version="1.3">
<params name="Championship" version="1.4">
<section name="Header">
<attstr name="name" val="Championship"/>
<attstr name="type" val="Championship"/>
@ -51,7 +51,7 @@
</section>
<section name="5">
<attstr name="name" val="wheel-2"/>
<attstr name="name" val="karwada"/>
<attstr name="category" val="circuit"/>
</section>
@ -176,9 +176,12 @@
</section>
<section name="Drivers">
<attnum name="maximum number" val="50"/>
<attstr name="focused module" val="human"/>
<attnum name="focused idx" val="3"/>
<attstr name="focused module" val="simplix_trb1"/>
<attnum name="focused idx" val="8"/>
<attstr name="rejected types" val="networkhuman"/>
<section name="1">
<attnum name="idx" val="8"/>
<attstr name="module" val="simplix_trb1"/>

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "../params.dtd">
<params name="Online Race" type="param" mode="mw" version="1.17">
<params name="Online Race" type="param" mode="mw" version="1.18">
<section name="Header">
<attstr name="name" val="Online Race"/>
@ -60,6 +60,7 @@
<section name="Drivers">
<attnum name="maximum number" val="40"/>
<attstr name="rejected types" val="human"/>
</section>
<section name="Configuration">

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "params.dtd">
<params name="Practice" version="1.3">
<params name="Practice" version="1.4">
<section name="Header">
<attstr name="name" val="Practice"/>
@ -70,6 +70,7 @@
<attnum name="maximum number" val="1"/>
<attstr name="focused module" val="human"/>
<attnum name="focused idx" val="1"/>
<attstr name="rejected types" val="networkhuman"/>
<section name="1">
<attnum name="idx" val="1"/>

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "../params.dtd">
<params name="Quick Race" type="param" mode="mw" version="1.17">
<params name="Quick Race" type="param" mode="mw" version="1.18">
<section name="Header">
<attstr name="name" val="Quick Race"/>
@ -63,9 +63,12 @@
</section>
<section name="Drivers">
<attnum name="maximum number" val="40"/>
<attstr name="focused module" val="human"/>
<attnum name="focused idx" val="6"/>
<attstr name="rejected types" val="networkhuman"/>
<section name="1">
<attnum name="idx" val="1"/>
<attstr name="module" val="usr_sc"/>

View file

@ -14,7 +14,7 @@
<!DOCTYPE params SYSTEM "params.dtd">
<params name="Challenge Race" version="1.3">
<params name="Challenge Race" version="1.4">
<section name="Header">
<attstr name="name" val="Challenge Race"/>
<attstr name="type" val="Single Event"/>
@ -175,9 +175,11 @@
</section>
<section name="Drivers">
<attnum name="maximum number" val="50"/>
<attstr name="focused module" val="human"/>
<attnum name="focused idx" val="3"/>
<attstr name="rejected types" val="networkhuman"/>
<section name="1">
<attnum name="idx" val="1"/>

View file

@ -15,7 +15,7 @@
<!DOCTYPE params SYSTEM "params.dtd">
<params name="Endurance Race" version="1.15">
<params name="Endurance Race" version="1.16">
<section name="Header">
<attstr name="name" val="Endurance Race"/>
@ -122,9 +122,12 @@
</section>
<section name="Drivers">
<attnum name="maximum number" val="50"/>
<attstr name="focused module" val="human"/>
<attnum name="focused idx" val="3"/>
<attstr name="rejected types" val="networkhuman"/>
<section name="1">
<attnum name="idx" val="3"/>
<attstr name="module" val="usr_trb1"/>