Redline/source/mapselection.cpp

339 lines
9.6 KiB
C++
Raw Normal View History

//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;
}