819 lines
26 KiB
C++
819 lines
26 KiB
C++
|
#include "stdtypes.h"
|
||
|
#include "reg_tool_3.h"
|
||
|
#include "rt3_redline.h"
|
||
|
|
||
|
|
||
|
#include <OpenGL/gl.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include "gametime.h"
|
||
|
#include "gamemem.h"
|
||
|
#include "fileio.h"
|
||
|
#include "rendercar.h"
|
||
|
#include "carphysics.h"
|
||
|
#include "screen.h"
|
||
|
#include "controls.h"
|
||
|
#include "environment.h"
|
||
|
#include "transparency.h"
|
||
|
#include "renderframe.h"
|
||
|
#include "text.h"
|
||
|
#include "interface.h"
|
||
|
#include "gameinitexit.h"
|
||
|
#include "carselection.h"
|
||
|
#include "config.h"
|
||
|
#include "interfaceutil.h"
|
||
|
#include "stencil.h"
|
||
|
#include "gamesystem.h"
|
||
|
#include "textures.h"
|
||
|
#include "challenges.h"
|
||
|
#include "gamesound.h"
|
||
|
#include "random.h"
|
||
|
|
||
|
#define REGISTERED (RT3_IsRegistered())
|
||
|
|
||
|
char *StripName(char *aName);
|
||
|
|
||
|
int CompareCars(const void *a,const void *b)
|
||
|
{
|
||
|
tCarDefinition *cara=(tCarDefinition*)FileGetParsedDataPtr(*(tFileRef*)a,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
tCarDefinition *carb=(tCarDefinition*)FileGetParsedDataPtr(*(tFileRef*)b,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
if(!REGISTERED)
|
||
|
if(cara->demoAvailable!=carb->demoAvailable)
|
||
|
return carb->demoAvailable-cara->demoAvailable;
|
||
|
return _stricmp(StripName(cara->carName),StripName(carb->carName));
|
||
|
}
|
||
|
|
||
|
void GetAvailableCars(tFileRef *availableCars,int *carCount,int onlyBuiltIn,int onlyAvailable)
|
||
|
{
|
||
|
*carCount=0;
|
||
|
for(int i=0;i<gFileTableSize;i++)
|
||
|
if(*carCount<kMaxCars)
|
||
|
if(char *extension=FileGetExtension(i))
|
||
|
if(!_stricmp(extension,kFileTypeCarDefinition))
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(i,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
if((car->builtIn||!onlyBuiltIn)&&HasChallengeRequirements(car->challengeRequirements,gConfig->challengeData))
|
||
|
availableCars[(*carCount)++]=i;
|
||
|
if(car->shiftUpRPM<car->maxRPM*0.8)
|
||
|
printf("%s: %f/%f\n",car->carName,car->shiftUpRPM,car->maxRPM);
|
||
|
}
|
||
|
if(!onlyAvailable)
|
||
|
for(int i=0;i<gFileTableSize;i++)
|
||
|
if(*carCount<kMaxCars)
|
||
|
if(char *extension=FileGetExtension(i))
|
||
|
if(!_stricmp(extension,kFileTypeCarDefinition))
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(i,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
if((car->builtIn||!onlyBuiltIn)&&!HasChallengeRequirements(car->challengeRequirements,gConfig->challengeData)&&!car->secret)
|
||
|
availableCars[(*carCount)++]=i;
|
||
|
}
|
||
|
qsort(availableCars,*carCount,sizeof(tFileRef),CompareCars);
|
||
|
}
|
||
|
|
||
|
#define kSpecsXPos 0.9
|
||
|
#define kSpecsYPos 0.6
|
||
|
#define kSpecsSize 0.03
|
||
|
#define kSpecsOffset 0.07
|
||
|
#define kSpecsAlign kTextAlignRight
|
||
|
|
||
|
//#define kColorsXPos 0.5
|
||
|
//#define kColorsYPos 0.2
|
||
|
#define kColorsXPos 0.42
|
||
|
#define kColorsYPos -0.3
|
||
|
#define kColorsWidth 0.04
|
||
|
#define kColorsHeight 0.02
|
||
|
//#define kColorsOffset 0.025
|
||
|
#define kColorsOffset 0.05
|
||
|
#define kPointerSize 0.03
|
||
|
|
||
|
void CarSelectionDrawBackground(int mode)
|
||
|
{
|
||
|
char title[256];
|
||
|
|
||
|
switch(mode)
|
||
|
{
|
||
|
case kCarSelectionQuickMode:
|
||
|
strcpy(title,"Select Car:");
|
||
|
break;
|
||
|
|
||
|
case kCarSelectionEnemyMode:
|
||
|
strcpy(title,"Select Opponent Car:");
|
||
|
break;
|
||
|
|
||
|
case kCarSelectionDisplayMode:
|
||
|
strcpy(title,"New Car Unlocked!");
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
InterfaceDrawBackground(-1,-1,0,0,0,0,1);
|
||
|
TextPrintfToBufferFormated(Vector(kTitlePosX,kTitlePosY),0.08,kTextAlignLeft,title);
|
||
|
}
|
||
|
|
||
|
void CarSelectionDrawCar(tFileRef carRef,float time,int addOns,int color)
|
||
|
{
|
||
|
tGameEntity carEntity,cameraEntity;
|
||
|
tCarPhysics *phys=(tCarPhysics*)MemoryAllocateZeroedBlock(sizeof(tCarPhysics));
|
||
|
cameraEntity.pos=Vector(0,1.5,0);
|
||
|
carEntity.pos=Vector(0,0,7);
|
||
|
*MatrixGetZVector(cameraEntity.dir)=!(carEntity.pos-cameraEntity.pos);
|
||
|
*MatrixGetYVector(cameraEntity.dir)=Vector(0,1,0);
|
||
|
MatrixReAdjust(cameraEntity.dir);
|
||
|
carEntity.pos.x-=0.5;
|
||
|
carEntity.pos.y-=1.0;
|
||
|
MatrixIdentity(carEntity.dir);
|
||
|
MatrixRotY(carEntity.dir,time*PI/4);
|
||
|
|
||
|
carEntity.renderType=kRenderTypeCar;
|
||
|
carEntity.physicsType=kPhysicsTypeCar;
|
||
|
carEntity.physicsData=carRef;
|
||
|
carEntity.physics=phys;
|
||
|
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(carRef,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
phys->car=*car;
|
||
|
phys->car.wheels=(tWheelDefinition*)MemoryAllocateBlock(sizeof(tWheelDefinition)*car->numWheels);
|
||
|
MemoryMove(phys->car.wheels,car->wheels,sizeof(tWheelDefinition)*car->numWheels);
|
||
|
phys->addOns=addOns;
|
||
|
phys->color=color;
|
||
|
InstallCarAddOns(phys);
|
||
|
car=&phys->car;
|
||
|
|
||
|
for(int i=0;i<car->numWheels;i++)
|
||
|
phys->wheels[i].suspension=car->wheels[i].maxSuspension/2;
|
||
|
|
||
|
tGameEntity *oldCameraEntity=gCameraEntity;
|
||
|
gCameraEntity=&cameraEntity;
|
||
|
SetupTranslation(carEntity.pos,carEntity.dir);
|
||
|
glColorMask(0,0,0,0);
|
||
|
glBegin(GL_QUADS);
|
||
|
glVertex3f(-100,0,100);
|
||
|
glVertex3f(100,0,100);
|
||
|
glVertex3f(100,0,-100);
|
||
|
glVertex3f(-100,0,-100);
|
||
|
glEnd();
|
||
|
glColorMask(1,1,1,1);
|
||
|
|
||
|
carEntity.pos.y=-1-car->wheels->pos.y+car->wheels->maxSuspension/2+car->wheels->radius;
|
||
|
SetupTranslation(carEntity.pos,carEntity.dir);
|
||
|
|
||
|
glPushAttrib(GL_LIGHTING_BIT+GL_POLYGON_BIT+GL_COLOR_BUFFER_BIT+GL_TEXTURE_BIT);
|
||
|
CarRenderEntity(&carEntity,gConfig->interiorDisplay?true:false,false);
|
||
|
glPopAttrib();
|
||
|
|
||
|
for(int i=1;i<=gConfig->stencil;i++)
|
||
|
{
|
||
|
gStencilZoom=0.9+0.1*i/(float)gConfig->stencil;
|
||
|
SetupTranslation(carEntity.pos,carEntity.dir);
|
||
|
glPushAttrib(GL_ENABLE_BIT+GL_POLYGON_BIT);
|
||
|
CarRenderEntityShadow(&carEntity,6);
|
||
|
glPopAttrib();
|
||
|
RenderStencilLayer(true,gConfig->stencil);
|
||
|
}
|
||
|
DrawTransparentPolys(NULL);
|
||
|
|
||
|
MemoryFreeBlock(phys->car.wheels);
|
||
|
MemoryFreeBlock(phys);
|
||
|
|
||
|
gCameraEntity=oldCameraEntity;
|
||
|
|
||
|
}
|
||
|
|
||
|
void CarSelectionDrawSpecs(tFileRef *availableCars,int numAvailable,int selected,int mode,int *available)
|
||
|
{
|
||
|
//if(fadeName)
|
||
|
//gTextOpacity=1;
|
||
|
|
||
|
for(int i=-3;i<=3;i++)
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[(selected+i+numAvailable)%numAvailable],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
TextPrintfToBufferFormatedColored(Vector(-kSpecsXPos,0.4-i*0.1-fabs(i)*0.008),0.05-fabs(i)*0.008,kTextAlignLeft,1,1,1,1-fabs(i*0.15)-(i?0.3:0),car->carName);
|
||
|
}
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[selected],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
// TextPrintfToBufferFormated(Vector(kSpecsXPos,0.5),0.05,kTextAlignLeft,car->carName);
|
||
|
|
||
|
|
||
|
// gTextOpacity=opacity;
|
||
|
float yPos=kSpecsYPos;
|
||
|
|
||
|
if(car->magic)
|
||
|
{
|
||
|
// TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-5*kSpecsOffset),kSpecsSize,kSpecsAlign,"Where we're going, we don't need specifications.");
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-0*kSpecsOffset),kSpecsSize,kSpecsAlign,"Where we're going, we don't need specifications.");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(car->numWheels>=4)
|
||
|
if(car->wheels[0].powered&&car->wheels[2].powered)
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-0.0),kSpecsSize,kSpecsAlign,"Drivetrain: \255#a\2554WD");
|
||
|
else if(car->wheels[0].powered)
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-0.0),kSpecsSize,kSpecsAlign,"Drivetrain: \255#a\255FWD");
|
||
|
else if(car->wheels[2].powered)
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-0.0),kSpecsSize,kSpecsAlign,"Drivetrain: \255#a\255RWD");
|
||
|
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-5*kSpecsOffset),kSpecsSize,kSpecsAlign,"Gearbox: \255#a\255%d Gears",car->numGears-2);
|
||
|
if(gConfig->metricUnits)
|
||
|
{
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-1*kSpecsOffset),kSpecsSize,kSpecsAlign,"Displacement: \255#a\255%1.1f L",car->displacement);
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-2*kSpecsOffset),kSpecsSize,kSpecsAlign,"Mass: \255#a\255%4.0f kg",car->mass);
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-3*kSpecsOffset),kSpecsSize,kSpecsAlign,"Power: \255#a\255%3.0f kw @ %4.0f RPM",car->power/1000,car->powerRPM);
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-4*kSpecsOffset),kSpecsSize,kSpecsAlign,"Torque: \255#a\255%3.0f Nm @ %4.0f RPM",car->torque,car->torqueRPM);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-1*kSpecsOffset),kSpecsSize,kSpecsAlign,"Displacement: \255#a\255%3.0f cui",car->displacement*61.023744);
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-2*kSpecsOffset),kSpecsSize,kSpecsAlign,"Mass: \255#a\255%4.0f lbs",car->mass*2.2046);
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-3*kSpecsOffset),kSpecsSize,kSpecsAlign,"Power: \255#a\255%3.0f hp @ %4.0f RPM",car->power/745.69987,car->powerRPM);
|
||
|
TextPrintfToBufferFormated(Vector(kSpecsXPos,yPos-4*kSpecsOffset),kSpecsSize,kSpecsAlign,"Torque: \255#a\255%3.0f lb-ft @ %4.0f RPM",car->torque/1.35628105,car->torqueRPM);
|
||
|
}
|
||
|
}
|
||
|
if(!car->demoAvailable&&!REGISTERED&&mode!=kCarSelectionEnemyMode)
|
||
|
TextPrintfToBufferFormatedColored(Vector(0.2,0),0.15,kTextAlignMiddle,1,1,1,0.5,"DEMO");
|
||
|
// TextPrintfToBufferFormatedColored(Vector(0.2,0.2),0.25,kTextAlignMiddle,1,1,1,0.8,"\255demo_car.png\255");
|
||
|
else if(!HasChallengeRequirements(car->challengeRequirements,gConfig->challengeData)&&mode!=kCarSelectionEnemyMode)
|
||
|
TextPrintfToBufferFormatedColored(Vector(0.2,0),0.15,kTextAlignMiddle,1,1,1,0.5,"LOCKED");
|
||
|
if(available)
|
||
|
*available=((car->demoAvailable||REGISTERED)&&HasChallengeRequirements(car->challengeRequirements,gConfig->challengeData))||mode==kCarSelectionEnemyMode;
|
||
|
gTextOpacity=1;
|
||
|
}
|
||
|
|
||
|
void CarSelectionDrawColors(tFileRef carRef,int color)
|
||
|
{
|
||
|
/* gTexturesQualityModifier=-255;
|
||
|
glPushAttrib(GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT);
|
||
|
glDisable(GL_LIGHTING);
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(carRef,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
|
||
|
glLoadIdentity();
|
||
|
glTranslatef(0.0f,0.0f,-1.0f);
|
||
|
TexturesSelectTex(FileGetReference("colorbevel.pct"));
|
||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
|
||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
|
||
|
glEnable(GL_BLEND);
|
||
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||
|
|
||
|
for(int i=0;i<car->numColors;i++)
|
||
|
{
|
||
|
glColor3fv(&(car->colors[i].x));
|
||
|
glBegin(GL_TRIANGLE_STRIP);
|
||
|
glTexCoord2d(1,1); glVertex2f(kColorsXPos+kColorsWidth,kColorsYPos-kColorsHeight/2-i*kColorsOffset);
|
||
|
glTexCoord2d(1,0); glVertex2f(kColorsXPos+kColorsWidth,kColorsYPos+kColorsHeight/2-i*kColorsOffset);
|
||
|
glTexCoord2d(0,1); glVertex2f(kColorsXPos,kColorsYPos-kColorsHeight/2-i*kColorsOffset);
|
||
|
glTexCoord2d(0,0); glVertex2f(kColorsXPos,kColorsYPos+kColorsHeight/2-i*kColorsOffset);
|
||
|
glEnd();
|
||
|
}
|
||
|
if(car->numColors)
|
||
|
{
|
||
|
if(color>=car->numColors)
|
||
|
color=car->numColors-1;
|
||
|
glColor3f(1,1,1);
|
||
|
TexturesSelectTex(FileGetReference("menupointer.tif"));
|
||
|
glBegin(GL_TRIANGLE_STRIP);
|
||
|
glTexCoord2d(1,1); glVertex2f(kColorsXPos-kColorsWidth+kPointerSize,kColorsYPos-kPointerSize/2-color*kColorsOffset);
|
||
|
glTexCoord2d(1,0); glVertex2f(kColorsXPos-kColorsWidth+kPointerSize,kColorsYPos+kPointerSize/2-color*kColorsOffset);
|
||
|
glTexCoord2d(0,1); glVertex2f(kColorsXPos-kColorsWidth,kColorsYPos-kPointerSize/2-color*kColorsOffset);
|
||
|
glTexCoord2d(0,0); glVertex2f(kColorsXPos-kColorsWidth,kColorsYPos+kPointerSize/2-color*kColorsOffset);
|
||
|
glEnd();
|
||
|
}
|
||
|
|
||
|
glPopAttrib();
|
||
|
gTexturesQualityModifier=0;*/
|
||
|
|
||
|
gTexturesQualityModifier=-255;
|
||
|
glPushAttrib(GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT);
|
||
|
glDisable(GL_LIGHTING);
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(carRef,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
|
||
|
glLoadIdentity();
|
||
|
glTranslatef(0.0f,0.0f,-1.0f);
|
||
|
TexturesSelectTex(FileGetReference("colorbevel.pct"));
|
||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
|
||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
|
||
|
glEnable(GL_BLEND);
|
||
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||
|
|
||
|
for(int i=0;i<car->numColors;i++)
|
||
|
{
|
||
|
glColor3fv(&(car->colors[i].x));
|
||
|
glBegin(GL_TRIANGLE_STRIP);
|
||
|
glTexCoord2d(1,1); glVertex2f(kColorsXPos-i*kColorsOffset+kColorsWidth,kColorsYPos-kColorsHeight/2);
|
||
|
glTexCoord2d(1,0); glVertex2f(kColorsXPos-i*kColorsOffset+kColorsWidth,kColorsYPos+kColorsHeight/2);
|
||
|
glTexCoord2d(0,1); glVertex2f(kColorsXPos-i*kColorsOffset,kColorsYPos-kColorsHeight/2);
|
||
|
glTexCoord2d(0,0); glVertex2f(kColorsXPos-i*kColorsOffset,kColorsYPos+kColorsHeight/2);
|
||
|
glEnd();
|
||
|
}
|
||
|
if(car->numColors)
|
||
|
{
|
||
|
if(color>=car->numColors)
|
||
|
color=car->numColors-1;
|
||
|
glColor3f(1,1,1);
|
||
|
TexturesSelectTex(FileGetReference("menupointer.tif"));
|
||
|
glBegin(GL_TRIANGLE_STRIP);
|
||
|
glTexCoord2d(0,1); glVertex2f(kColorsXPos-color*kColorsOffset+kColorsWidth/2+kPointerSize/2,kColorsYPos-kColorsHeight*2);
|
||
|
glTexCoord2d(1,1); glVertex2f(kColorsXPos-color*kColorsOffset+kColorsWidth/2+kPointerSize/2,kColorsYPos-kColorsHeight*2+kPointerSize);
|
||
|
glTexCoord2d(0,0); glVertex2f(kColorsXPos-color*kColorsOffset+kColorsWidth/2-kPointerSize/2,kColorsYPos-kColorsHeight*2);
|
||
|
glTexCoord2d(1,0); glVertex2f(kColorsXPos-color*kColorsOffset+kColorsWidth/2-kPointerSize/2,kColorsYPos-kColorsHeight*2+kPointerSize);
|
||
|
glEnd();
|
||
|
}
|
||
|
|
||
|
glPopAttrib();
|
||
|
gTexturesQualityModifier=0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void InterfaceCarSelectionRenderLoadScreen(float time,tFileRef *availableCars,int numAvailable,int selected,int mode,int addOns,int color,int drawColor,int *demoAvailable,float carFade,float totalFade)
|
||
|
{
|
||
|
glPushMatrix();
|
||
|
glPushAttrib(GL_LIGHTING_BIT);
|
||
|
glDisable(GL_LIGHTING);
|
||
|
glClear(GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT);
|
||
|
|
||
|
CarSelectionDrawBackground(mode);
|
||
|
|
||
|
CarSelectionDrawSpecs(availableCars,numAvailable,selected,mode,demoAvailable);
|
||
|
|
||
|
InterfaceDrawBackgroundFade(carFade,false);
|
||
|
|
||
|
TextPrintfToBufferFormated(Vector(0.2,0.1),0.05,kTextAlignMiddle,"Loading...");
|
||
|
|
||
|
CarSelectionDrawColors(availableCars[selected],color);
|
||
|
|
||
|
TextPrintBuffer(1,false);
|
||
|
TextClearBuffer();
|
||
|
|
||
|
InterfaceDrawBackgroundFade(totalFade,false);
|
||
|
|
||
|
ScreenBlit();
|
||
|
glPopAttrib();
|
||
|
glPopMatrix();
|
||
|
}
|
||
|
|
||
|
void InterfaceCarSelectionRender(float time,tFileRef *availableCars,int numAvailable,int selected,int mode,int addOns,int color,int drawColor,int *demoAvailable,float carFade,float totalFade)
|
||
|
{
|
||
|
glPushMatrix();
|
||
|
glPushAttrib(GL_LIGHTING_BIT);
|
||
|
glEnable(GL_LIGHTING);
|
||
|
SetupLighting();
|
||
|
|
||
|
glClear(GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT);
|
||
|
|
||
|
CarSelectionDrawBackground(mode);
|
||
|
/*tInterfaceMenuDescribtion menu;
|
||
|
InterfaceInitMenu(&menu,0,"");
|
||
|
|
||
|
InterfaceRenderReplay(NULL,0,&menu);*/
|
||
|
|
||
|
if(selected!=-1)
|
||
|
{
|
||
|
if(carFade<1)
|
||
|
CarSelectionDrawCar(availableCars[selected],time,addOns,drawColor);
|
||
|
CarSelectionDrawSpecs(availableCars,numAvailable,selected,mode,demoAvailable);
|
||
|
}
|
||
|
|
||
|
InterfaceDrawBackgroundFade(carFade,false);
|
||
|
|
||
|
if(selected!=-1&&mode!=kCarSelectionDisplayMode)
|
||
|
CarSelectionDrawColors(availableCars[selected],color);
|
||
|
|
||
|
TextPrintBuffer(1,false);
|
||
|
TextClearBuffer();
|
||
|
|
||
|
InterfaceDrawBackgroundFade(totalFade,false);
|
||
|
|
||
|
ScreenBlit();
|
||
|
glPopAttrib();
|
||
|
glPopMatrix();
|
||
|
}
|
||
|
|
||
|
int SelectCarByChar(char ch)
|
||
|
{
|
||
|
tFileRef availableCars[kMaxCars];
|
||
|
int carCount;
|
||
|
GetAvailableCars(availableCars,&carCount,false,false);
|
||
|
|
||
|
for(int i=0;i<carCount;i++)
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[i],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
if(toupper(StripName(car->carName)[0])>=ch)
|
||
|
return i;
|
||
|
}
|
||
|
return carCount-1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
int InterfaceCarSelectionQuick(int *selection,int mode)//,int (*Callback)(void*),void *userData,int *callbackResponse)
|
||
|
{
|
||
|
tInterfaceMenuDescribtion menu;
|
||
|
tFileRef availableCars[kMaxCars];
|
||
|
int carCount;
|
||
|
GetAvailableCars(availableCars,&carCount,false,false);
|
||
|
|
||
|
InterfaceInitMenu(&menu,carCount,"Car Quick-Selection");
|
||
|
|
||
|
menu.scrollEnable=true;
|
||
|
menu.returnOnSpace=true;
|
||
|
for(int i=0;i<menu.numItems;i++)
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[i],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
strcpy(menu.items[i].label,car->carName);
|
||
|
menu.items[i].size*=0.7;
|
||
|
menu.items[i].lineSpacing*=0.7;
|
||
|
if(!HasChallengeRequirements(car->challengeRequirements,gConfig->challengeData)&&mode!=kCarSelectionEnemyMode)
|
||
|
menu.items[i].flags |= kInterfaceMenuItemDisabled;
|
||
|
if(!car->demoAvailable&&!REGISTERED&&mode!=kCarSelectionEnemyMode)
|
||
|
menu.items[i].flags |= kInterfaceMenuItemDisabled;
|
||
|
}
|
||
|
// menu.TimerCallback=Callback;
|
||
|
// menu.userData=userData;
|
||
|
menu.initialSelection=*selection;
|
||
|
*selection=InterfaceGetUserMenuSelection(&menu);
|
||
|
if(*selection == kInterfaceMenuEsc)
|
||
|
{
|
||
|
*selection=-2;
|
||
|
return true;
|
||
|
}
|
||
|
if(*selection & kInterfaceMenuSpaceFlag)
|
||
|
{
|
||
|
*selection&=kInterfaceMenuItemMask;
|
||
|
return false;
|
||
|
}
|
||
|
InterfaceDisposeMenu(&menu);
|
||
|
return true;
|
||
|
}
|
||
|
*/
|
||
|
int InterfaceCarSelectionInput(int carCount,int *selection,int mode,int *color,int demoAvailable,int maxColors,int *drawImmediate)
|
||
|
{
|
||
|
int key;
|
||
|
char ch=toupper(GetKeyInput(&key));
|
||
|
if(ch>='A'&&ch<='Z')
|
||
|
*selection=SelectCarByChar(ch);
|
||
|
*drawImmediate=false;
|
||
|
switch(key)
|
||
|
{
|
||
|
// case kInterfaceKeyLeft:
|
||
|
case kInterfaceKeyUp:
|
||
|
(*selection)--;
|
||
|
*color=0;
|
||
|
PlayInterfaceSound(FileGetReference("menu.wav"));
|
||
|
break;
|
||
|
// case kInterfaceKeyRight:
|
||
|
case kInterfaceKeyDown:
|
||
|
(*selection)++;
|
||
|
*color=0;
|
||
|
PlayInterfaceSound(FileGetReference("menu.wav"));
|
||
|
break;
|
||
|
|
||
|
// case kInterfaceKeyUp:
|
||
|
case kInterfaceKeyRight:
|
||
|
(*color)--;
|
||
|
if(*color<0)
|
||
|
*color=maxColors-1;
|
||
|
if(*color<0)
|
||
|
*color=0;
|
||
|
PlayInterfaceSound(FileGetReference("menu.wav"));
|
||
|
break;
|
||
|
|
||
|
// case kInterfaceKeyDown:
|
||
|
case kInterfaceKeyLeft:
|
||
|
*color=(*color+1)%maxColors;
|
||
|
if(*color>=maxColors)
|
||
|
*color=0;
|
||
|
PlayInterfaceSound(FileGetReference("menu.wav"));
|
||
|
break;
|
||
|
|
||
|
case kInterfaceKeyEsc:
|
||
|
case kInterfaceKeyDelete:
|
||
|
PlayInterfaceSound(FileGetReference("esc.wav"));
|
||
|
*selection=-2;
|
||
|
return true;
|
||
|
|
||
|
case kInterfaceKeyReturn:
|
||
|
case kInterfaceKeyEnter:
|
||
|
if(demoAvailable)
|
||
|
{
|
||
|
PlayInterfaceSound(FileGetReference("select.wav"));
|
||
|
return true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
/* case kInterfaceKeySpace:
|
||
|
*drawImmediate=true;
|
||
|
return InterfaceCarSelectionQuick(selection,mode);//,mode,Callback,userData,callbackResponse);
|
||
|
break;*/
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void SelectNextCar(tFileRef *car,UInt8 *color,int onlyAvailable,int onlyDemo)
|
||
|
{
|
||
|
int availableCars[kMaxCars];
|
||
|
int carCount;
|
||
|
int selection=0;
|
||
|
GetAvailableCars(availableCars,&carCount,false,onlyAvailable);
|
||
|
|
||
|
for(int i=0;i<carCount;i++)
|
||
|
if(*car==availableCars[i])
|
||
|
selection=i;
|
||
|
|
||
|
tCarDefinition *c;
|
||
|
do{
|
||
|
selection=(selection+1)%carCount;
|
||
|
c=(tCarDefinition*)FileGetParsedDataPtr(availableCars[selection],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
if(color)
|
||
|
if(c->numColors)
|
||
|
*color=RandomInt(0,c->numColors);
|
||
|
else
|
||
|
*color=0;
|
||
|
}while(!c->demoAvailable&&!REGISTERED&&onlyDemo);
|
||
|
|
||
|
*car=availableCars[selection];
|
||
|
// gConfig->lastCar=*car;
|
||
|
}
|
||
|
|
||
|
void SelectPrevCar(tFileRef *car,UInt8 *color,int onlyAvailable,int onlyDemo)
|
||
|
{
|
||
|
int availableCars[kMaxCars];
|
||
|
int carCount;
|
||
|
int selection=0;
|
||
|
GetAvailableCars(availableCars,&carCount,false,onlyAvailable);
|
||
|
|
||
|
for(int i=0;i<carCount;i++)
|
||
|
if(*car==availableCars[i])
|
||
|
selection=i;
|
||
|
|
||
|
tCarDefinition *c;
|
||
|
do{
|
||
|
selection--;
|
||
|
if(selection<0)
|
||
|
selection+=carCount;
|
||
|
c=(tCarDefinition*)FileGetParsedDataPtr(availableCars[selection],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
if(color)
|
||
|
if(c->numColors)
|
||
|
*color=RandomInt(0,c->numColors);
|
||
|
else
|
||
|
*color=0;
|
||
|
}while(!c->demoAvailable&&!REGISTERED&&onlyDemo);
|
||
|
|
||
|
*car=availableCars[selection];
|
||
|
// gConfig->lastCar=*car;
|
||
|
}
|
||
|
|
||
|
void SetupLighting();
|
||
|
|
||
|
int InterfaceCarSelection(tFileRef *car,int mode,UInt8 *pColor,int (*Callback)(void*),void *userData,int *callbackResponse)
|
||
|
{
|
||
|
int availableCars[kMaxCars];
|
||
|
int selection=1;
|
||
|
int carCount;
|
||
|
int color=*pColor;
|
||
|
int oldColor=*pColor;
|
||
|
int demoAvailable=true;
|
||
|
int drawImmediate=false;
|
||
|
tFileRef curCar;
|
||
|
float carFade=0;
|
||
|
|
||
|
GetAvailableCars(availableCars,&carCount,false,false);
|
||
|
for(int i=0;i<carCount;i++)
|
||
|
if(*car==availableCars[i])
|
||
|
selection=i;
|
||
|
|
||
|
tEnvironment *oldEnv=gEnvironment;
|
||
|
tMapEnv* oldMapEnv=gMapEnv;
|
||
|
gMapEnv=NULL;
|
||
|
LoadEnvironment(FileGetReference("showroom.senv"));
|
||
|
glDisable(GL_LIGHTING);
|
||
|
|
||
|
float startTime=TimeGetSeconds();
|
||
|
float curTime=0;
|
||
|
|
||
|
int maxColors=1;
|
||
|
|
||
|
curCar=selection==-1?-1:availableCars[selection];
|
||
|
|
||
|
do{
|
||
|
selection=selection%carCount;
|
||
|
if(selection<0) selection+=carCount;
|
||
|
float dt=curTime;
|
||
|
curTime=TimeGetSeconds()-startTime;
|
||
|
dt=curTime-dt;
|
||
|
|
||
|
if((curCar!=(selection==-1?-1:availableCars[selection]))||color!=oldColor)
|
||
|
{
|
||
|
if(selection!=-1)
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[selection],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
int colorLoaded=false;
|
||
|
if(car->numColors>0)
|
||
|
colorLoaded=car->colorLoaded[color];
|
||
|
if(carFade>=3||(colorLoaded&&carFade>=1))
|
||
|
{
|
||
|
curCar=availableCars[selection];
|
||
|
oldColor=color;
|
||
|
}
|
||
|
else
|
||
|
carFade+=dt/0.2;
|
||
|
}
|
||
|
else if(carFade>=1)
|
||
|
{
|
||
|
curCar=-1;
|
||
|
oldColor=color;
|
||
|
}
|
||
|
else
|
||
|
carFade+=dt/0.2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
carFade-=dt/0.2;
|
||
|
if(carFade<1&&carFade+dt/0.2>=1&&curCar!=-1)
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[selection],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
int colorLoaded=false;
|
||
|
if(car->numColors>0)
|
||
|
colorLoaded=car->colorLoaded[color];
|
||
|
if(!colorLoaded)
|
||
|
{
|
||
|
InterfaceCarSelectionRenderLoadScreen(curTime,availableCars,carCount,selection,mode,0,color,oldColor,&demoAvailable,carFade,1-(curTime/0.2));
|
||
|
InterfaceCarSelectionRender(curTime,availableCars,carCount,selection,mode,0,color,oldColor,&demoAvailable,carFade,1-(curTime/0.2));
|
||
|
FlushKeys();
|
||
|
curTime=TimeGetSeconds()-startTime;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if(drawImmediate)
|
||
|
{
|
||
|
carFade=1;
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[selection],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
car->colorLoaded[color]=true;
|
||
|
}
|
||
|
if(carFade<0)carFade=0;
|
||
|
InterfaceCarSelectionRender(curTime,availableCars,carCount,selection,mode,0,color,oldColor,&demoAvailable,carFade,1-(curTime/0.2));
|
||
|
SystemPoll(false);
|
||
|
if(Callback)
|
||
|
{
|
||
|
*callbackResponse=Callback(userData);
|
||
|
if(*callbackResponse!=-1)
|
||
|
{
|
||
|
gEnvironment=oldEnv;
|
||
|
gMapEnv=oldMapEnv;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
if(selection!=-1)
|
||
|
{
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(availableCars[selection],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
maxColors=car->numColors;
|
||
|
if(maxColors==1)maxColors=1;
|
||
|
}
|
||
|
else
|
||
|
maxColors=1;
|
||
|
}
|
||
|
while(!InterfaceCarSelectionInput(carCount,&selection,mode,&color,demoAvailable,maxColors,&drawImmediate));
|
||
|
glEnable(GL_LIGHTING);
|
||
|
gEnvironment=oldEnv;
|
||
|
gMapEnv=oldMapEnv;
|
||
|
|
||
|
float endTime=curTime+0.2;
|
||
|
if(selection>=0)
|
||
|
while(curTime<endTime)
|
||
|
{
|
||
|
curTime=TimeGetSeconds()-startTime;
|
||
|
InterfaceCarSelectionRender(curTime,availableCars,carCount,selection,mode,0,color,oldColor,&demoAvailable,carFade,1-((endTime-curTime)/0.2));
|
||
|
}
|
||
|
if(selection!=-2)
|
||
|
{
|
||
|
*car=availableCars[selection];
|
||
|
*pColor=color;
|
||
|
}
|
||
|
return selection!=-2;
|
||
|
}
|
||
|
|
||
|
enum{
|
||
|
kOpponentNumOpponents,
|
||
|
kOpponent1,
|
||
|
kOpponent2,
|
||
|
kOpponent3,
|
||
|
kOpponent4,
|
||
|
kOpponent5,
|
||
|
kOpponent6orOK,
|
||
|
kOpponent7orNumOptions,
|
||
|
kOpponent8,
|
||
|
kOpponent9,
|
||
|
kOpponent10,
|
||
|
kOpponent11,
|
||
|
kOpponentOK,
|
||
|
kOpponentNumOptions
|
||
|
};
|
||
|
|
||
|
int InterfaceSelectOpponentCars(int *numOpponents,tFileRef *opponents,UInt8 *colors,int (*Callback)(void*),void *userData)
|
||
|
{
|
||
|
int setNumOpponents=gConfig->numEnemies;
|
||
|
if(setNumOpponents>(gConfig->allowHugeGames?11:5))
|
||
|
setNumOpponents=(gConfig->allowHugeGames?11:5);
|
||
|
int callBackResponse;
|
||
|
tInterfaceMenuDescribtion menu;
|
||
|
InterfaceInitMenu(&menu,gConfig->allowHugeGames?kOpponentNumOptions:kOpponent7orNumOptions,"Select Opponents");
|
||
|
|
||
|
int availableCars[kMaxCars];
|
||
|
int carCount;
|
||
|
GetAvailableCars(availableCars,&carCount,false,false);
|
||
|
|
||
|
|
||
|
// for(int i=0;i<menu.numItems;i++)
|
||
|
// strcpy(menu.items[i].describtion,itemStrings[i]);
|
||
|
|
||
|
|
||
|
strcpy(menu.items[(gConfig->allowHugeGames?kOpponentOK:kOpponent6orOK)].label,"Accept");
|
||
|
menu.items[(gConfig->allowHugeGames?kOpponentOK:kOpponent6orOK)-1].lineSpacing*=1.5;
|
||
|
menu.items[kOpponent1-1].lineSpacing*=1.5;
|
||
|
menu.TimerCallback=Callback;
|
||
|
menu.userData=userData;
|
||
|
|
||
|
menu.items[kOpponentNumOpponents].flags|=kInterfaceMenuItemArrowInput;
|
||
|
|
||
|
for(int i=0;i<11;i++)
|
||
|
{
|
||
|
opponents[i]=gConfig->opponentCars[i];
|
||
|
colors[i]=gConfig->opponentColors[i];
|
||
|
if(opponents[i]==-1||opponents[i]==0)
|
||
|
{
|
||
|
opponents[i]=availableCars[0];
|
||
|
colors[i]=0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for(int i=kOpponent1;i<=(gConfig->allowHugeGames?kOpponent11:kOpponent5);i++)
|
||
|
{
|
||
|
menu.items[i].flags|=kInterfaceMenuItemArrowInput;
|
||
|
if(gConfig->allowHugeGames)
|
||
|
{
|
||
|
menu.items[i].size*=0.6;
|
||
|
menu.items[i].lineSpacing*=0.6;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int exit=false;
|
||
|
int zoom=false;
|
||
|
do{
|
||
|
sprintf(menu.items[kOpponentNumOpponents].label,"Number of Opponents: \255#a\255%d",setNumOpponents);
|
||
|
for(int i=kOpponent1;i<=(gConfig->allowHugeGames?kOpponent11:kOpponent5);i++)
|
||
|
{
|
||
|
if(i-kOpponent1<setNumOpponents)
|
||
|
menu.items[i].flags&=~kInterfaceMenuItemDisabled;
|
||
|
else
|
||
|
menu.items[i].flags|=kInterfaceMenuItemDisabled;
|
||
|
tCarDefinition *c=(tCarDefinition*)FileGetParsedDataPtr(opponents[i-kOpponent1],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
sprintf(menu.items[i].label,"Opponent %d: \255#a\255%s",i-kOpponent1+1,c->carName);
|
||
|
}
|
||
|
int sel=InterfaceGetUserMenuSelection(&menu);
|
||
|
switch(menu.initialSelection=(sel&kInterfaceMenuItemMask))
|
||
|
{
|
||
|
case kOpponentNumOpponents:
|
||
|
if(sel&kInterfaceMenuRightArrow){
|
||
|
if(setNumOpponents<(gConfig->allowHugeGames?11:5))
|
||
|
setNumOpponents++;
|
||
|
}
|
||
|
else if(sel&kInterfaceMenuLeftArrow){
|
||
|
if(setNumOpponents>0)
|
||
|
setNumOpponents--;
|
||
|
}
|
||
|
else
|
||
|
exit=true;
|
||
|
break;
|
||
|
case kOpponent6orOK:
|
||
|
if(!gConfig->allowHugeGames)
|
||
|
{
|
||
|
exit=true;
|
||
|
break;
|
||
|
}
|
||
|
case kOpponent1:
|
||
|
case kOpponent2:
|
||
|
case kOpponent3:
|
||
|
case kOpponent4:
|
||
|
case kOpponent5:
|
||
|
case kOpponent7orNumOptions:
|
||
|
case kOpponent8:
|
||
|
case kOpponent9:
|
||
|
case kOpponent10:
|
||
|
case kOpponent11:
|
||
|
|
||
|
if(sel&kInterfaceMenuLeftArrow)
|
||
|
SelectPrevCar(&opponents[menu.initialSelection-kOpponent1],&colors[menu.initialSelection-kOpponent1],false,false);
|
||
|
else if(sel&kInterfaceMenuRightArrow)
|
||
|
SelectNextCar(&opponents[menu.initialSelection-kOpponent1],&colors[menu.initialSelection-kOpponent1],false,false);
|
||
|
else
|
||
|
InterfaceCarSelection(&opponents[menu.initialSelection-kOpponent1],kCarSelectionEnemyMode,&colors[menu.initialSelection-kOpponent1],Callback,userData,&callBackResponse);
|
||
|
break;
|
||
|
case kOpponentOK:
|
||
|
case kInterfaceMenuEsc:
|
||
|
exit=true;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}while(!exit);
|
||
|
for(int i=0;i<11;i++)
|
||
|
{
|
||
|
gConfig->opponentCars[i]=opponents[i];
|
||
|
gConfig->opponentColors[i]=colors[i];
|
||
|
}
|
||
|
*numOpponents=gConfig->numEnemies=setNumOpponents;
|
||
|
InterfaceDisposeMenu(&menu);
|
||
|
return menu.initialSelection!=kInterfaceMenuEsc;
|
||
|
}
|