339 lines
9.6 KiB
C++
339 lines
9.6 KiB
C++
//mapselection.cpp
|
|
//let the user select a map
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "gamemem.h"
|
|
#include "fileio.h"
|
|
#include "gameinitexit.h"
|
|
#include "parser.h"
|
|
#include "config.h"
|
|
#include "environment.h"
|
|
#include "interfaceutil.h"
|
|
#include "mapselection.h"
|
|
#include "controls.h"
|
|
|
|
#define kMaxMaps 1024
|
|
#define kMaxEnvironments 64
|
|
|
|
char *StripName(char *aName)
|
|
{
|
|
while(*aName==' '||*aName=='\t')aName++;
|
|
while(*aName=='\255')
|
|
{
|
|
aName++;
|
|
while(*aName!='\255'&&*aName!=0)
|
|
aName++;
|
|
if(*aName=='\255')
|
|
aName++;
|
|
while(*aName==' '||*aName=='\t')aName++;
|
|
}
|
|
return aName;
|
|
}
|
|
|
|
int CompareMaps(const void *a,const void *b)
|
|
{
|
|
tMapInfo *mapa=(tMapInfo*)FileGetParsedDataPtr(*(tFileRef*)a,kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
tMapInfo *mapb=(tMapInfo*)FileGetParsedDataPtr(*(tFileRef*)b,kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
return _stricmp(StripName(mapa->name),StripName(mapb->name));
|
|
}
|
|
|
|
//get a list of available map files
|
|
void GetAvailableMaps(int *availableMaps,int *mapCount)
|
|
{
|
|
*mapCount=0;
|
|
for(int i=0;i<gFileTableSize;i++)
|
|
if(*mapCount<kMaxMaps)
|
|
if(char *extension=FileGetExtension(i))
|
|
if(!_stricmp(extension,kFileTypeMapDefinition))
|
|
{
|
|
tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(i,kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
if(!mapInfo->hideMap)
|
|
availableMaps[(*mapCount)++]=i;
|
|
}
|
|
qsort(availableMaps,*mapCount,sizeof(tFileRef),CompareMaps);
|
|
}
|
|
|
|
//get a list of available environment files
|
|
void GetAvailableEnvironments(int *availableEnvironments,int *environmentCount,int timeTrial)
|
|
{
|
|
*environmentCount=0;
|
|
for(int i=0;i<gFileTableSize;i++)
|
|
if(*environmentCount<kMaxEnvironments)
|
|
if(char *extension=FileGetExtension(i))
|
|
if(!_stricmp(extension,kFileTypeEnvironmentDefinition))
|
|
{
|
|
if(!timeTrial)
|
|
availableEnvironments[(*environmentCount)++]=i;
|
|
}
|
|
}
|
|
|
|
void SelectNextMap(tFileRef *map)
|
|
{
|
|
int availableMaps[kMaxMaps];
|
|
int mapCount;
|
|
int selection=0;
|
|
|
|
GetAvailableMaps(availableMaps,&mapCount);
|
|
for(int i=0;i<mapCount;i++)
|
|
if(*map==availableMaps[i])
|
|
selection=i;
|
|
|
|
selection=(selection+1)%mapCount;
|
|
|
|
*map=availableMaps[selection];
|
|
gConfig->lastRoad=*map;
|
|
}
|
|
|
|
void SelectPrevMap(tFileRef *map)
|
|
{
|
|
int availableMaps[kMaxMaps];
|
|
int mapCount;
|
|
int selection=0;
|
|
|
|
GetAvailableMaps(availableMaps,&mapCount);
|
|
for(int i=0;i<mapCount;i++)
|
|
if(*map==availableMaps[i])
|
|
selection=i;
|
|
|
|
selection--;
|
|
if(selection<0)
|
|
selection+=mapCount;
|
|
|
|
*map=availableMaps[selection];
|
|
gConfig->lastRoad=*map;
|
|
}
|
|
|
|
int SelectMapByChar(char ch)
|
|
{
|
|
tFileRef availableMaps[kMaxMaps];
|
|
int mapCount;
|
|
GetAvailableMaps(availableMaps,&mapCount);
|
|
|
|
for(int i=0;i<mapCount;i++)
|
|
{
|
|
tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(availableMaps[i],kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
if(toupper(StripName(mapInfo->name)[0])>=ch)
|
|
return i;
|
|
}
|
|
return mapCount-1;
|
|
}
|
|
|
|
typedef struct{
|
|
float t;
|
|
int *mapSelection;
|
|
int (*Callback)(void*);
|
|
void *userData;
|
|
} tMapSelectionCallbackUserData;
|
|
|
|
|
|
enum{
|
|
kMapSelectionMap,
|
|
kMapSelectionReverse,
|
|
kMapSelectionLaps,
|
|
kMapSelectionEnvironment,
|
|
// kMapSelectionMode,
|
|
kMapSelectionAccept,
|
|
kMapSelectionExit,
|
|
kNumMapSelectionItems
|
|
};
|
|
|
|
int MapSelectionCallback(void *ud)
|
|
{
|
|
char ch=toupper(PeekKeyInput(NULL));
|
|
if(ch>='A'&&ch<='Z')
|
|
{
|
|
*((tMapSelectionCallbackUserData*)ud)->mapSelection=SelectMapByChar(ch);
|
|
GetKeyInput(NULL);
|
|
return kNumMapSelectionItems;
|
|
}
|
|
if(((tMapSelectionCallbackUserData*)ud)->Callback)
|
|
return ((tMapSelectionCallbackUserData*)ud)->Callback(((tMapSelectionCallbackUserData*)ud)->userData);
|
|
return -1;
|
|
}
|
|
|
|
int InterfaceMapSelection(tGameInfo *gInfo,int (*Callback)(void*),void *userData,int timeTrial)
|
|
{
|
|
tFileRef availableMaps[kMaxMaps];
|
|
int availableEnvironments[kMaxEnvironments];
|
|
int mapSelection=0;
|
|
int environmentSelection=0;
|
|
int mapCount,environmentCount;
|
|
int lapCount=gConfig->lastLaps;
|
|
int reverse=gConfig->reverse;
|
|
|
|
tMapSelectionCallbackUserData ud;
|
|
ud.t=INFINITY;
|
|
ud.mapSelection = &mapSelection;
|
|
ud.Callback=Callback;
|
|
ud.userData=userData;
|
|
|
|
GetAvailableMaps(availableMaps,&mapCount);
|
|
for(int i=0;i<mapCount;i++)
|
|
if(gConfig->lastRoad==availableMaps[i])
|
|
mapSelection=i;
|
|
GetAvailableEnvironments(availableEnvironments,&environmentCount,timeTrial);
|
|
for(int i=0;i<environmentCount;i++)
|
|
if(gConfig->lastEnv==availableEnvironments[i])
|
|
environmentSelection=i;
|
|
|
|
tInterfaceMenuDescribtion menu;
|
|
InterfaceInitMenu(&menu,kNumMapSelectionItems,"Select Map");
|
|
menu.RenderCallback=InterfaceRenderReplay;
|
|
InterfaceMenuZoomAnimation(&menu,-1,true);
|
|
|
|
menu.items[kMapSelectionReverse-1].lineSpacing*=1.5;
|
|
menu.items[kMapSelectionAccept-1].lineSpacing*=4.25;
|
|
strcpy(menu.items[kMapSelectionExit].label,"Cancel");
|
|
menu.imageXScale=kMapImageXStretch;
|
|
menu.imageYScale=kMapImageYStretch;
|
|
menu.imageXPos+=0.1;
|
|
menu.imageYPos-=0.03;
|
|
menu.TimerCallback=MapSelectionCallback;
|
|
menu.userData=&ud;
|
|
menu.returnOnSpace=true;
|
|
|
|
for(int i=0;i<=kMapSelectionEnvironment;i++)
|
|
menu.items[i].flags|=kInterfaceMenuItemArrowInput;
|
|
|
|
for(int i=kMapSelectionReverse;i<=kMapSelectionEnvironment;i++)
|
|
{
|
|
menu.items[i].size*=0.8;
|
|
menu.items[i].lineSpacing*=0.8;
|
|
}
|
|
|
|
int exit=false;
|
|
int sel;
|
|
|
|
do{
|
|
tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(availableMaps[mapSelection],kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
tEnvironment *environment=(tEnvironment*)FileGetParsedDataPtr(availableEnvironments[environmentSelection],kParserTypeEnvironmentDesc,sizeof(tEnvironment));
|
|
int demook=false;
|
|
if(availableMaps[mapSelection]==FileGetReference("city2.mapinfo"))demook=true;
|
|
if(availableMaps[mapSelection]==FileGetReference("highspeed.mapinfo"))demook=true;
|
|
menu.image=mapInfo->image;
|
|
|
|
menu.imageAlpha=1.0;
|
|
strcpy(menu.items[kMapSelectionAccept].label,"Accept");
|
|
menu.items[kMapSelectionAccept].flags=0;
|
|
if((!mapInfo->loop)||gInfo->numLaps==-1)
|
|
menu.items[kMapSelectionLaps].flags|=kInterfaceMenuItemDisabled;
|
|
else
|
|
menu.items[kMapSelectionLaps].flags&=~kInterfaceMenuItemDisabled;
|
|
menu.items[kMapSelectionEnvironment].flags&=~kInterfaceMenuItemDisabled;
|
|
menu.items[kMapSelectionReverse].flags&=~kInterfaceMenuItemDisabled;
|
|
|
|
sprintf(menu.items[kMapSelectionMap].label,"Selected Map: \255#a\255%s",mapInfo->name);
|
|
sprintf(menu.items[kMapSelectionReverse].label,"Direction: \255#a\255%s",reverse?"Reverse":"Normal");
|
|
if(gInfo->numLaps!=-1)
|
|
if(!mapInfo->loop)
|
|
sprintf(menu.items[kMapSelectionLaps].label,"Number of Laps: \255#a\255Not Looped");
|
|
else
|
|
sprintf(menu.items[kMapSelectionLaps].label,"Number of Laps: \255#a\255%d",lapCount);
|
|
else
|
|
sprintf(menu.items[kMapSelectionLaps].label,"Number of Laps: \255#a\255Unlimited");
|
|
if(mapInfo->useAltEnv&&environment->hasAltEnv)
|
|
environment=(tEnvironment*)FileGetParsedDataPtr(environment->altEnv,kParserTypeEnvironmentDesc,sizeof(tEnvironment));
|
|
sprintf(menu.items[kMapSelectionEnvironment].label,"Weather: \255#a\255%s",environment->name);
|
|
|
|
sel=InterfaceGetUserMenuSelection(&menu);
|
|
if(sel==kNumMapSelectionItems)
|
|
menu.initialSelection=0;
|
|
else
|
|
switch(menu.initialSelection=(sel&kInterfaceMenuItemMask))
|
|
{
|
|
case kMapSelectionMap:
|
|
if(sel&kInterfaceMenuLeftArrow)
|
|
do{
|
|
mapSelection--;
|
|
if(mapSelection<0)mapSelection=mapCount-1;
|
|
mapInfo=(tMapInfo*)FileGetParsedDataPtr(availableMaps[mapSelection],kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
}while(gInfo->numLaps==-1&&!mapInfo->loop);
|
|
else if(sel&kInterfaceMenuRightArrow)
|
|
do{
|
|
mapSelection=(mapSelection+1)%mapCount;
|
|
mapInfo=(tMapInfo*)FileGetParsedDataPtr(availableMaps[mapSelection],kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
}while(gInfo->numLaps==-1&&!mapInfo->loop);
|
|
else
|
|
exit=true;
|
|
break;
|
|
|
|
case kMapSelectionReverse:
|
|
if(sel&(kInterfaceMenuRightArrow|kInterfaceMenuLeftArrow))
|
|
reverse=!reverse;
|
|
else
|
|
exit=true;
|
|
break;
|
|
|
|
case kMapSelectionLaps:
|
|
if(sel&kInterfaceMenuLeftArrow){
|
|
lapCount--;
|
|
if(lapCount<1)lapCount=kMaxLaps;
|
|
}
|
|
else if(sel&kInterfaceMenuRightArrow){
|
|
lapCount++;
|
|
if(lapCount>kMaxLaps)lapCount=1;
|
|
}
|
|
else
|
|
exit=true;
|
|
break;
|
|
|
|
case kMapSelectionEnvironment:
|
|
if(sel&kInterfaceMenuLeftArrow){
|
|
environmentSelection--;
|
|
if(environmentSelection<0)environmentSelection=environmentCount-1;
|
|
}
|
|
else if(sel&kInterfaceMenuRightArrow)
|
|
environmentSelection=(environmentSelection+1)%environmentCount;
|
|
else
|
|
exit=true;
|
|
break;
|
|
|
|
/* case kMapSelectionMode:
|
|
if(sel&kInterfaceMenuLeftArrow){
|
|
gInfo->arcade--;
|
|
if(gInfo->arcade<0)
|
|
gInfo->arcade=(sel&kInterfaceMenuEasterEgg?2:1);
|
|
}
|
|
else if(sel&kInterfaceMenuRightArrow)
|
|
gInfo->arcade=(gInfo->arcade+1)%(sel&kInterfaceMenuEasterEgg?3:2);
|
|
else exit=true;
|
|
break;
|
|
*/
|
|
case kInterfaceMenuOK:
|
|
case kMapSelectionAccept:
|
|
exit=true;
|
|
break;
|
|
|
|
case kInterfaceMenuEsc:
|
|
case kMapSelectionExit:
|
|
exit=true;
|
|
break;
|
|
}
|
|
}while(!exit);
|
|
|
|
InterfaceDisposeMenu(&menu);
|
|
|
|
sel&=kInterfaceMenuItemMask;
|
|
if(sel!=kInterfaceMenuEsc&&sel!=kMapSelectionExit)
|
|
{
|
|
gInfo->reverse=reverse;
|
|
if(gInfo->numLaps!=-1)
|
|
gInfo->numLaps=lapCount;
|
|
gInfo->map=availableMaps[mapSelection];
|
|
tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(gInfo->map,kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
|
if(!mapInfo->loop)
|
|
{
|
|
gInfo->numLaps=1;
|
|
}
|
|
gInfo->environment=availableEnvironments[environmentSelection];
|
|
|
|
gConfig->lastRoad=availableMaps[mapSelection];
|
|
gConfig->reverse=reverse;
|
|
gConfig->lastLaps=lapCount;
|
|
gConfig->lastEnv=availableEnvironments[environmentSelection];
|
|
// gConfig->arcade=gInfo->arcade;
|
|
return true;
|
|
}
|
|
return false;
|
|
} |