Redline/source/interface.cpp

553 lines
17 KiB
C++
Raw Permalink Normal View History

//interface.cpp
//the game's main menu screen
#include <OpenGL/gl.h>
#include "gametime.h"
#include <string.h>
#include "fileio.h"
#include "textures.h"
#include "controls.h"
#include "screen.h"
#include "gameinitexit.h"
#include "gameframe.h"
#include "initexit.h"
#include "text.h"
#include "config.h"
#include "interface.h"
#include "carselection.h"
#include "mapselection.h"
#include "random.h"
#include "environment.h"
#include "writeout.h"
#include "challenges.h"
#include "interfaceutil.h"
#include "renderframe.h"
#include "log.h"
#include "gamesystem.h"
#include "gamesound.h"
#include "interfacemultiplayer.h"
#include "tracker.h"
#include <AmbrosiaTools/stdtypes.h>
tGameInfo gInterfaceGInfo;
//initializes the user interface
void InterfaceInit()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-1.0f);
}
void StartBackgroundReplay()
{
gMapInfo=(tMapInfo*)FileGetParsedDataPtr(gInterfaceGInfo.map,kParserTypeMapInfoDesc,sizeof(tMapInfo));
LoadEnvironment(gInterfaceGInfo.environment);
gInterfaceGInfo.network=false;
gReplay=true;
gGameInfo=&gInterfaceGInfo;
gReplayAutoCam=true;
if(!(gGameInfo->numLaps==-1&&gBestLapTime==0))
gCurrentLapStart=0;
StartReplay();
gReplayViewedEntityID=0;
/* gFrameCount=0;
gGraphFrameCount=0;
gStartTime=TimeGetSeconds();*/
}
int SelectRaceMode(tFileRef map,int (*TimerCallback)(void*),void *userData)
{
tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(map,kParserTypeMapInfoDesc,sizeof(tMapInfo));
tInterfaceMenuDescribtion menu;
InterfaceInitMenu(&menu,5,"Select Gameplay Mode");
menu.RenderCallback=InterfaceRenderReplay;
menu.initialSelection=gConfig->arcade;
strcpy(menu.items[0].label,"Simulation");
strcpy(menu.items[0].describtion,"Simulation Mode tries to resemble real-life car physics as close as possible. Different cars may handle completely different depending on their mass distribution, drivetrain setup and many other factors.");
strcpy(menu.items[1].label,"Arcade");
strcpy(menu.items[1].describtion,"Arcade Mode puts emphasis on playability and easy handling of cars, but is vastly inaccurate compared to real-life physics. Different cars handle quite similar and differ only in their acceleration and top speed characteristics.");
strcpy(menu.items[2].label,"Turbo Arcade");
strcpy(menu.items[2].describtion,"Arcade Mode on steroids.");
strcpy(menu.items[3].label,"Strict");
strcpy(menu.items[3].describtion,"Strict mode is like Simulation mode with modified collision physics to encourage clean racing.");
strcpy(menu.items[menu.numItems-1].label,"Cancel");
menu.items[menu.numItems-2].lineSpacing*=1.5;
menu.imageXScale=kMapImageXStretch;
menu.imageYScale=kMapImageYStretch;
menu.imageXPos+=0.1;
menu.imageYPos-=0.03;
menu.TimerCallback=TimerCallback;
menu.userData=userData;
menu.image=mapInfo->image;
menu.descPos=Vector(-0.9,-0.6);
int sel=InterfaceGetUserMenuSelection(&menu);
InterfaceDisposeMenu(&menu);
return sel==menu.numItems-1||sel==kInterfaceMenuEsc?-1:sel;
}
void InterfaceQuickRace()
{
tGameInfo gInfo;
InitGInfo(&gInfo);
//let user select a map...
if(InterfaceMapSelection(&gInfo,NULL,NULL,false))
{
int raceMode=SelectRaceMode(gInfo.map,NULL,NULL);
if(raceMode==-1)
return;
else
gConfig->arcade=raceMode;
gInfo.arcade=gConfig->arcade;
tFileRef playerCar=gConfig->lastCar;
UInt8 playerColor=gConfig->lastColor;
//...and a car...
if(InterfaceCarSelection(&playerCar,kCarSelectionQuickMode,&playerColor,NULL,NULL,NULL))
{
gConfig->lastCar=playerCar;
gConfig->lastColor=playerColor;
tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(gInfo.map,kParserTypeMapInfoDesc,sizeof(tMapInfo));
int numPlayers=mapInfo->maxPlayers;
//...and opponets
if(InterfaceSelectOpponentCars(&numPlayers,gInfo.playerCars+1,gInfo.playerColors+1,NULL,NULL))
{
gInfo.numPlayers=numPlayers+1;
gInfo.playerID=0;
gInfo.playerCars[gInfo.playerID]=playerCar;
gInfo.playerColors[gInfo.playerID]=playerColor;
//and run the game
RunGame(&gInfo);
TeaserScreen();
}
}
}
}
void InterfaceTimeTrial()
{
tGameInfo gInfo;
InitGInfo(&gInfo);
gInfo.numPlayers=1;
gInfo.numLaps=-1;
//let user select a map...
if(InterfaceMapSelection(&gInfo,NULL,NULL,true))
{
int raceMode=SelectRaceMode(gInfo.map,NULL,NULL);
if(raceMode==-1)
return;
else
gConfig->arcade=raceMode;
gInfo.arcade=gConfig->arcade;
//...and a car...
gInfo.playerCars[0]=gConfig->lastCar;
gInfo.playerColors[0]=gConfig->lastColor;
if(InterfaceCarSelection(gInfo.playerCars,kCarSelectionQuickMode,gInfo.playerColors,NULL,NULL,NULL))
{
gConfig->lastCar=gInfo.playerCars[0];
gConfig->lastColor=gInfo.playerColors[0];
gLocalRecord=0;
for(int i=0;i<gConfig->numPersonalRecords;i++)
if(gConfig->records[i].map==gInfo.map&&gConfig->records[i].car==gInfo.playerCars[0]
&&gConfig->records[i].mode==gInfo.arcade&&gConfig->records[i].direction==gInfo.reverse)
gLocalRecord=gConfig->records[i].time;
RunGame(&gInfo);
WriteOutFile(FileGetReference(kConfigFileName),gConfig,kParserTypeConfigDesc);
TeaserScreen();
}
}
}
void InterfaceOptions();
enum{
kButtonQuickRace,
kButtonTimeTrial,
kButtonMultiplayer,
kButtonCareer,
kButtonOptions,
kButtonAbout,
kButtonQuit,
kNumButtons
};
void InterfaceDisplayRegisterName(void *userData,int selection)
{
// TextPrintfToBufferFormated(Vector(1.0,-0.9),0.03,kTextAlignRight,"%s%s",RT3_IsRegistered()?"Registered to: ":"",RT3_GetDisplayName());
TextPrintfToBufferFormated(Vector(1.0,0.95),0.03,kTextAlignRight,kVersionString);
// TextPrintfToBufferFormated(Vector(-1.0,-0.9),0.03,kTextAlignLeft,kVersionString);
}
#define kTopSize 0.141
void InterfaceRenderReplay(void *userData,int selection,void *menu)
{
float *t,v=0;
static int inited=false;
if(userData)
t=((float*)userData);
else
t=&v;
if(gConfig->showReplays)//&&0)
{
gBackgroundReplay=true;
if(!inited)
{
gEnableTextureLoad=false;
gNumTexturesRequested=0;
gClipEnable=false;
RenderFrame(false);
gClipEnable=true;
gNumTexturesLoaded=0;
gEnableTextureLoad=true;
gDisabledRestart=0;
for(int i=0;i<gFileTableSize;i++)
{
if(gFileTable[i].tagged&&!gFileTable[i].parsed)
{
gTexturesQualityModifier=gFileTable[i].tagged+1;
TexturesSelectTex(i);
SystemPoll(false);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-1.0f);
glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
gTexturesQualityModifier=-255;
TexturesSelectTex(FileGetReference("logo.pct"));
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,-kBackgroundYStretch);
glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch,kBackgroundYStretch);
glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,-kBackgroundYStretch);
glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
glEnd();
ScreenBlit();
glPopAttrib();
}
}
inited=true;
}
ReplayFrame();
if(gSystemSuspended)
PauseGame();
gBackgroundReplay=false;
}
glLoadIdentity();
glTranslatef(0.0f,0.0f,-1.0f);
glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
gTexturesQualityModifier=-255;
if(menu)
{
if(((tInterfaceMenuDescribtion*)menu)->background!=kFileErr||!gConfig->showReplays)
{
if(((tInterfaceMenuDescribtion*)menu)->background!=kFileErr)
TexturesSelectTex(((tInterfaceMenuDescribtion*)menu)->background);
else
TexturesSelectTex(FileGetReference("background.tif"));
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
if(!gConfig->showReplays)
glDisable(GL_BLEND);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glTexCoord2d(1,0); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch);
glTexCoord2d(0,1); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glTexCoord2d(0,0); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
glEnd();
glEnable(GL_BLEND);
}
if(((tInterfaceMenuDescribtion*)menu)->image!=kFileErr)
{
TexturesSelectTex(((tInterfaceMenuDescribtion*)menu)->image);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glColor4f(1,1,1,((tInterfaceMenuDescribtion*)menu)->imageAlpha);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos+((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos-((tInterfaceMenuDescribtion*)menu)->imageYScale);
glTexCoord2d(1,0); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos+((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos+((tInterfaceMenuDescribtion*)menu)->imageYScale);
glTexCoord2d(0,1); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos-((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos-((tInterfaceMenuDescribtion*)menu)->imageYScale);
glTexCoord2d(0,0); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos-((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos+((tInterfaceMenuDescribtion*)menu)->imageYScale);
glEnd();
glColor4f(1,1,1,1);
}
TexturesSelectTex(FileGetReference("menustripe.tif"));
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex2f((2)*kScreenXPos, 0.7*kScreenYPos);
glTexCoord2d(1,0); glVertex2f((2)*kScreenXPos, 1.0*kScreenYPos);
glTexCoord2d(0,1); glVertex2f((-2)*kScreenXPos,0.7*kScreenYPos);
glTexCoord2d(0,0); glVertex2f((-2)*kScreenXPos,1.0*kScreenYPos);
glEnd();
glDisable(GL_TEXTURE_2D);
glColor4f(0,0,0,1);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
glVertex2f(-2*kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glVertex2f(-2*kBackgroundXStretch,kBackgroundYStretch);
glEnd();
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(2*kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glVertex2f(2*kBackgroundXStretch,kBackgroundYStretch);
glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glVertex2f(kBackgroundXStretch,kBackgroundYStretch);
glEnd();
glColor4f(1,1,1,1);
glEnable(GL_TEXTURE_2D);
}
else if(!gConfig->showReplays)
{
glDisable(GL_BLEND);
TexturesSelectTex(FileGetReference("background.tif"));
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glTexCoord2d(1,0); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch);
glTexCoord2d(0,1); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);
glTexCoord2d(0,0); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
glEnd();
glEnable(GL_BLEND);
}
if(*t<0)
*t=TimeGetSeconds();
float time=TimeGetSeconds();
float d=1.5-(time-*t)*2;
if(d<0)d=0;
if(userData&&!isinf(*t))
{
TexturesSelectTex(FileGetReference("menulogo.tif"));
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex2f((0.3-d)*kScreenXPos, 0.7*kScreenYPos);
glTexCoord2d(1,0); glVertex2f((0.3-d)*kScreenXPos, 1.0*kScreenYPos);
glTexCoord2d(0,1); glVertex2f((-0.95-d)*kScreenXPos,0.7*kScreenYPos);
glTexCoord2d(0,0); glVertex2f((-0.95-d)*kScreenXPos,1.0*kScreenYPos);
glEnd();
TexturesSelectTex(FileGetReference("logo.pct"));
glColor4f(1,1,1,d);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,-kBackgroundYStretch);
glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch,kBackgroundYStretch);
glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,-kBackgroundYStretch);
glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
glEnd();
TextPrintfToBufferFormated(Vector(1.0,-0.9),0.03,kTextAlignRight,"%s%s",RT3_IsRegistered()?"Registered to: ":"",RT3_GetDisplayName());
TextPrintfToBufferFormated(Vector(1.0,0.88),0.03,kTextAlignRight,kVersionString);
}
gTexturesQualityModifier=0;
glPopAttrib();
}
int InterfaceConfirmQuit()
{
tInterfaceMenuDescribtion menu;
InterfaceInitMenu(&menu,2,"Do you really want to quit?");
menu.background=kFileErr;
menu.RenderCallback=InterfaceRenderReplay;
char itemStrings[][32]={"Quit","Cancel"};
menu.items[0].lineSpacing*=1.3;
for(int i=0;i<menu.numItems;i++)
strcpy(menu.items[i].label,itemStrings[i]);
InterfaceMenuZoomAnimation(&menu,-1,true);
int sel=InterfaceGetUserMenuSelection(&menu);
InterfaceDisposeMenu(&menu);
return !sel;
}
void InterfaceReplayMenu()
{
tInterfaceMenuDescribtion menu;
tFileRef logs[kMaxLogs];
int logCount;
GetLogs(logs,&logCount);
InterfaceInitMenu(&menu,logCount,"Choose a replay file to play:");
menu.background=kFileErr;
menu.scrollEnable=true;
menu.RenderCallback=InterfaceRenderReplay;
for(int i=0;i<menu.numItems;i++)
{
strcpy(menu.items[i].label,FileGetName(logs[i]));
menu.items[i].size*=0.7;
menu.items[i].lineSpacing*=0.7;
}
int sel=InterfaceGetUserMenuSelection(&menu);
InterfaceDisposeMenu(&menu);
if(sel!=kInterfaceMenuEsc)
{
if(!LogLoad(logs[sel],&gInterfaceGInfo))
LogLoad(FileGetReference("bullit.redlog"),&gInterfaceGInfo);
gGameEnd=false;
gGameInfo=&gInterfaceGInfo;
StartBackgroundReplay();
gEnableTextureLoad=false;
gNumTexturesRequested=0;
ReplayFrame();
RenderFrame(false);
gNumTexturesLoaded=0;
gEnableTextureLoad=true;
gDisabledRestart=0;
for(int i=0;i<gFileTableSize;i++)
{
if(gFileTable[i].tagged&&!gFileTable[i].parsed)
{
// InterfaceDrawStatusBar("Loading Textures...",gFileTable[i].name,gNumTexturesLoaded/(float)gNumTexturesRequested);
if(gNumTexturesRequested>0)
InterfaceDrawStatusBar("Loading Textures...","Please Wait",gNumTexturesLoaded/(float)gNumTexturesRequested);
TexturesSelectTex(i);
SystemPoll(true);
}
}
StartBackgroundReplay();
gFrameCount=gReplayOldFrameCount;
RunReplay();
SoundSilence();
FlushKeys();
}
}
//run the applications main loop
void InterfaceMainLoop()
{
float userData=-1;
tInterfaceMenuDescribtion menu;
InterfaceInitMenu(&menu,kNumButtons+1,"");
menu.numItems=kNumButtons;
char itemStrings[][32]={"Quick Race","Time Trial","Multiplayer","Challenges","Options","About","Quit",""};
for(int i=0;i<menu.numItems+1;i++)
{
strcpy(menu.items[i].label,itemStrings[i]);
menu.items[i].size*=1.25;
menu.items[i].lineSpacing*=1.25;
}
menu.itemsYPos+=0.05;
menu.items[kButtonQuit-1].lineSpacing*=1.5;
menu.easterEggEnable=true;
menu.userData=&userData;
menu.background=kFileErr;
tFileRef logs[kMaxLogs];
int logCount;
GetLogs(logs,&logCount);
if(!LogLoad(logs[RandomInt(0,logCount)],&gInterfaceGInfo))
LogLoad(FileGetReference("bullit.redlog"),&gInterfaceGInfo);
gGameInfo=&gInterfaceGInfo;
StartBackgroundReplay();
menu.RenderCallback=InterfaceRenderReplay;
//menu.RenderCallback=InterfaceDisplayRegisterName;
//menu.image=FileGetReference("logo.pct");
int exit=false;
do{
char *version,*url;
if(TrackerVersionCheck(&version))
{
menu.numItems=kNumButtons+1;
sprintf(menu.items[kButtonQuit].label,"\255#r\255Upgrade to version %s",version);
strcpy(menu.items[kNumButtons].label,itemStrings[kButtonQuit]);
}
InterfaceMenuZoomAnimation(&menu,-1,true);
switch(menu.initialSelection=InterfaceGetUserMenuSelection(&menu))
{
case kButtonQuickRace:
InterfaceQuickRace();
break;
case kButtonTimeTrial:
InterfaceTimeTrial();
break;
case kButtonCareer:
InterfaceChallenge();
break;
case kButtonMultiplayer://let the user start a multiplayer game
InterfaceMultiplayerLobby();
break;
case kButtonOptions://game settings
InterfaceOptions();
break;
case kButtonAbout:
TextScrollFile(FileGetReference("credits.txt"));
break;
case kInterfaceMenuReplayKey:
InterfaceReplayMenu();
break;
case kButtonQuit://leave the main loop
case kInterfaceMenuEsc:
case kNumButtons:
if(menu.initialSelection==menu.numItems-2)
{
TrackerGetNewVersion();
exit=true;
break;
}
if(InterfaceConfirmQuit())
exit=true;
break;
}
}while(!exit);
InterfaceDisposeMenu(&menu);
}