772 lines
20 KiB
C++
772 lines
20 KiB
C++
|
//gameinitexit.cpp
|
||
|
//initialize a new game and dispose all the game structures after the game has ended
|
||
|
|
||
|
|
||
|
#include <OpenGL/gl.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include "gametime.h"
|
||
|
#include "gamemem.h"
|
||
|
#include "entities.h"
|
||
|
#include "fileio.h"
|
||
|
#include "sky.h"
|
||
|
#include "carphysics.h"
|
||
|
#include "gameframe.h"
|
||
|
#include "roads.h"
|
||
|
#include "parser.h"
|
||
|
#include "network.h"
|
||
|
#include "environment.h"
|
||
|
#include "config.h"
|
||
|
#include "gameinitexit.h"
|
||
|
#include "error.h"
|
||
|
#include "gamesound.h"
|
||
|
#include "text.h"
|
||
|
#include "renderframe.h"
|
||
|
#include "controls.h"
|
||
|
#include "tracks.h"
|
||
|
#include "stencil.h"
|
||
|
#include "log.h"
|
||
|
#include "networkphysics.h"
|
||
|
#include "random.h"
|
||
|
#include "particles.h"
|
||
|
#include "interfaceutil.h"
|
||
|
#include "tracker.h"
|
||
|
#include "screen.h"
|
||
|
#include "textures.h"
|
||
|
#include "gamesystem.h"
|
||
|
#include "interface.h"
|
||
|
#include "interfacemultiplayer.h"
|
||
|
#include "initexit.h"
|
||
|
|
||
|
/*
|
||
|
#if __option(profile)
|
||
|
#include <profiler.h>
|
||
|
#endif
|
||
|
*/
|
||
|
|
||
|
|
||
|
//the map info structure
|
||
|
tMapInfo *gMapInfo=NULL;
|
||
|
|
||
|
//the game info structure
|
||
|
tGameInfo *gGameInfo=NULL;
|
||
|
|
||
|
//pointers to the game entities of the cars participating in the game
|
||
|
tGameEntity *gCarEntities[kMaxPlayers];
|
||
|
|
||
|
tGameEntity *gGhostEntity;
|
||
|
|
||
|
tMapEnv *gMapEnv=NULL;
|
||
|
|
||
|
//the check points along the track (invisible, used only for lead/trail calculation)
|
||
|
tCheckPoint gCheckPoints[kNumCheckPoints];
|
||
|
|
||
|
|
||
|
int gNumCornerSigns;
|
||
|
tCornerSign gCornerSigns[kMaxCornerSigns];
|
||
|
|
||
|
//is this a replay being watched?
|
||
|
int gReplay=false;
|
||
|
int gBackgroundReplay=false;
|
||
|
int gReplayAutoCam=false;
|
||
|
int gReplayViewedEntityID;
|
||
|
int gReplayNextCam;
|
||
|
int gReplayOldFrameCount;
|
||
|
|
||
|
void InitGInfo(tGameInfo *gInfo)
|
||
|
{
|
||
|
gInfo->inited=false;
|
||
|
gInfo->version=0;
|
||
|
gInfo->numPlayers=0;
|
||
|
gInfo->numNetPlayers=0;
|
||
|
gInfo->reverse=0;
|
||
|
gInfo->environment=kFileErr;
|
||
|
gInfo->numLaps=0;
|
||
|
gInfo->map=kFileErr;
|
||
|
gInfo->network=false;
|
||
|
gInfo->playerID=0;
|
||
|
gInfo->arcade=kGameModeSim;
|
||
|
gInfo->maxTime=0;
|
||
|
gInfo->unused1=false;
|
||
|
gInfo->unused2=false;
|
||
|
gInfo->carsOnSpeed=gConfig->carsOnSpeed;
|
||
|
gInfo->demolition=gConfig->demolition;
|
||
|
gInfo->playerInited[0]=true;
|
||
|
strcpy(gInfo->environmentName,"");
|
||
|
strcpy(gInfo->mapName,"");
|
||
|
for(int i=0;i<kMaxPlayers;i++)
|
||
|
{
|
||
|
gInfo->playerCars[i]=kFileErr;
|
||
|
gInfo->playerColors[i]=0;
|
||
|
gInfo->playerAddOns[i]=0;
|
||
|
gInfo->netID[i]=0;
|
||
|
gInfo->ping[i]=0;
|
||
|
gInfo->playerVersions[i]=0;
|
||
|
strcpy(gInfo->playerCarNames[i],"");
|
||
|
strcpy(gInfo->playerNames[i],"");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//load map describtion from the file refered to by ref.
|
||
|
void ProcessMapInfo()
|
||
|
{
|
||
|
if(gMapInfo->reverse)
|
||
|
gGameInfo->reverse=!gGameInfo->reverse;
|
||
|
|
||
|
//get road types data
|
||
|
gRoadTypes=(tRoadTypeList*)FileGetParsedDataPtr(gMapInfo->roadTypes,kParserTypeRoadTypeDesc,sizeof(tRoadTypeList));
|
||
|
|
||
|
//initialize game entities defined by map
|
||
|
for(int i=0;i<gMapInfo->numObjs;i++)
|
||
|
{
|
||
|
if(gMapInfo->obj[i].envFlags==0||(gMapInfo->obj[i].envFlags&gEnvironment->envFlags))
|
||
|
{
|
||
|
//create a new entity
|
||
|
tGameEntity *entity;
|
||
|
entity=EntityNew(gFirstEntity);
|
||
|
entity->renderType=kRenderTypeModel;
|
||
|
|
||
|
//get entity position and direction from map info
|
||
|
entity->pos=gMapInfo->obj[i].pos;
|
||
|
EulerAnglesToMatrix(gMapInfo->obj[i].dir*kDegreeRadians,entity->dir);
|
||
|
|
||
|
//get extension of file describing entity
|
||
|
char *extension=FileGetExtension(gMapInfo->obj[i].model);
|
||
|
|
||
|
entity->physics=MemoryAllocateBlock(sizeof(int));
|
||
|
*((int*)entity->physics)=gMapInfo->obj[i].color;
|
||
|
|
||
|
entity->untouchable=gMapInfo->obj[i].untouchable;
|
||
|
|
||
|
if(extension)
|
||
|
//is this entity just a model (no interaction with the game, just graphics).
|
||
|
if(!_stricmp(extension,kFileTypeModel))
|
||
|
entity->renderData=gMapInfo->obj[i].model;
|
||
|
|
||
|
//or is it a solid entity?
|
||
|
else if(!_stricmp(extension,kFileTypeSolidEntity))
|
||
|
{
|
||
|
//initialize entity
|
||
|
entity->physicsType=kPhysicsTypeSolid;
|
||
|
entity->physicsData=gMapInfo->obj[i].model;
|
||
|
entity->physicsMachine=kPhysicsLocal;
|
||
|
|
||
|
tSolidEntityPhysics *ent=(tSolidEntityPhysics*)FileGetParsedDataPtr(entity->physicsData,kParserTypeSolidEntityDesc,sizeof(tSolidEntityPhysics));
|
||
|
if(ent->randomColor)
|
||
|
*((int*)entity->physics)=RandomInt(0,ent->numColors);
|
||
|
|
||
|
entity->renderData=ent->model;
|
||
|
if(ent->movable)
|
||
|
entity->lastActivity=-1000;
|
||
|
}
|
||
|
else if(!_stricmp(extension,kFileTypeCarDefinition))
|
||
|
{
|
||
|
//initialize entity
|
||
|
entity->renderType=kRenderTypeCar;
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(gMapInfo->obj[i].model,kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
entity->renderData=car->model;
|
||
|
entity->physicsType=kPhysicsTypeCar;
|
||
|
entity->controlType=kControlTypeNone;
|
||
|
entity->physicsData=gMapInfo->obj[i].model;
|
||
|
entity->physics=MemoryAllocateZeroedBlock(sizeof(tCarPhysics));
|
||
|
entity->physicsMachine=gGameInfo->network?(i==gGameInfo->playerID?kPhysicsLocal:kPhysicsRemote):kPhysicsLocal;
|
||
|
entity->lastActivity=-1000;
|
||
|
tCarPhysics *phys=(tCarPhysics*)entity->physics;
|
||
|
phys->car=*car;
|
||
|
phys->car.wheels=(tWheelDefinition*)MemoryAllocateBlock(sizeof(tWheelDefinition)*car->numWheels);
|
||
|
MemoryMove(phys->car.wheels,car->wheels,sizeof(tWheelDefinition)*car->numWheels);
|
||
|
phys->color=gMapInfo->obj[i].color;
|
||
|
}
|
||
|
|
||
|
//is it something we don't understand?
|
||
|
else
|
||
|
{
|
||
|
char error[256];
|
||
|
sprintf(error,"Illegal File Type %s Specified for Object",extension);
|
||
|
FailWithErrorString(error);
|
||
|
}
|
||
|
}
|
||
|
//else PrintConsoleString("%s: %d/%d",FileGetName(gMapInfo->obj[i].model),gMapInfo->obj[i].envFlags,gEnvironment->envFlags);
|
||
|
}
|
||
|
|
||
|
gMapEnv=NULL;
|
||
|
for(int i=0;i<gMapInfo->numMapEnvs;i++)
|
||
|
if(gMapInfo->mapEnv[i].envFlags&gEnvironment->envFlags)
|
||
|
gMapEnv=gMapInfo->mapEnv+i;
|
||
|
|
||
|
if(gMapEnv)
|
||
|
if(gMapEnv->fogBegin)
|
||
|
{
|
||
|
GLfloat fogColor[4];
|
||
|
*(tVector3*)fogColor=gMapEnv->fogColor;
|
||
|
fogColor[3]=1;
|
||
|
glFogfv(GL_FOG_COLOR,fogColor);
|
||
|
glFogf(GL_FOG_START,gMapEnv->fogBegin);
|
||
|
glFogf(GL_FOG_END,gMapEnv->fogEnd);
|
||
|
}
|
||
|
//calculate road checkpoints
|
||
|
if(gMapInfo->loop)
|
||
|
RoadInitCheckPoints(gMapInfo->startPos);
|
||
|
else
|
||
|
{
|
||
|
RoadInitCheckPoints(gMapInfo->startPos,gMapInfo->finishPos);
|
||
|
gGameInfo->numLaps=1;
|
||
|
}
|
||
|
RoadInitCornerSigns();
|
||
|
}
|
||
|
|
||
|
void CalcCamera();
|
||
|
|
||
|
void InitCars()
|
||
|
{
|
||
|
for(int i=0;i<gGameInfo->numPlayers;i++)
|
||
|
{
|
||
|
//get car describtion
|
||
|
tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(gGameInfo->playerCars[i],kParserTypeCarDesc,sizeof(tCarDefinition));
|
||
|
|
||
|
//initialize car entity
|
||
|
tGameEntity *entity;
|
||
|
entity=EntityNew(gFirstEntity);
|
||
|
entity->renderType=kRenderTypeCar;
|
||
|
entity->renderData=car->model;
|
||
|
entity->physicsType=kPhysicsTypeCar;
|
||
|
entity->controlType=(i==gGameInfo->playerID?kControlTypeUserInput:kControlTypeAIInput);
|
||
|
//entity->controlType=kControlTypeAIInput;
|
||
|
entity->physicsData=gGameInfo->playerCars[i];
|
||
|
entity->physics=MemoryAllocateZeroedBlock(sizeof(tCarPhysics));
|
||
|
entity->physicsMachine=gGameInfo->network?(i==gGameInfo->playerID?kPhysicsLocal:kPhysicsRemote):kPhysicsLocal;
|
||
|
if(i>=gGameInfo->numNetPlayers&&gGameInfo->playerID==0)
|
||
|
entity->physicsMachine=kPhysicsLocal;
|
||
|
gCarEntities[i]=entity;
|
||
|
|
||
|
//position car at start position
|
||
|
int startAtEnd=(gGameInfo->reverse&&!gMapInfo->loop);
|
||
|
tVector3 startPos=startAtEnd?gMapInfo->finishPos:gMapInfo->startPos;
|
||
|
|
||
|
if(gGameInfo->numLaps==-1&&gMapInfo->loop)
|
||
|
{
|
||
|
int roadIndex=0;
|
||
|
float side=0,speed;
|
||
|
startPos=RoadGetNextWaypoint(gMapInfo->startPos,&roadIndex,&side,&speed,-700);
|
||
|
|
||
|
}
|
||
|
tVector3 startDir=RoadGetDir(RoadGetPosition(startPos,0,NULL));
|
||
|
|
||
|
entity->pos=startPos-startDir*((i/2)*10+gMapInfo->startLineOffset+(i%2?gMapInfo->carOffset:0))+!(startDir%Vector(0,1,0))*(i%2?-1:1)*gMapInfo->startCenterOffset;
|
||
|
entity->netPos=entity->pos;
|
||
|
*MatrixGetZVector(entity->dir)=startDir;
|
||
|
*MatrixGetYVector(entity->dir)=Vector(0,1,0);
|
||
|
MatrixReAdjust(entity->dir);
|
||
|
|
||
|
tCarPhysics *phys=(tCarPhysics*)entity->physics;
|
||
|
|
||
|
if(i==gGameInfo->playerID)
|
||
|
gViewedEntity=entity;
|
||
|
|
||
|
//set up car specs
|
||
|
if(startAtEnd)
|
||
|
phys->checkPoint=kNumCheckPoints-1;
|
||
|
phys->car=*car;
|
||
|
phys->car.wheels=(tWheelDefinition*)MemoryAllocateBlock(sizeof(tWheelDefinition)*car->numWheels);
|
||
|
MemoryMove(phys->car.wheels,car->wheels,sizeof(tWheelDefinition)*car->numWheels);
|
||
|
phys->addOns=gGameInfo->playerAddOns[i];
|
||
|
phys->color=gGameInfo->playerColors[i];
|
||
|
phys->aiPowerCycle=RandomFl(0,2*PI);
|
||
|
phys->aiRouteCycle=RandomFl(0,2*PI);
|
||
|
phys->position=RoadGetPosition(entity->pos,entity->lastRoadIndex,NULL);
|
||
|
if(i>0)
|
||
|
{
|
||
|
tCarPhysics *phys2=(tCarPhysics*)gCarEntities[0]->physics;
|
||
|
if(phys->position>phys2->position&&!gGameInfo->reverse)
|
||
|
phys->lap=-1;
|
||
|
else if(phys->position<phys2->position&&gGameInfo->reverse)
|
||
|
phys->lap=-1;
|
||
|
}
|
||
|
|
||
|
if(gGameInfo->playerNames[i][0])
|
||
|
phys->plateName=gGameInfo->playerNames[i];
|
||
|
|
||
|
for(int j=0;j<5;j++)
|
||
|
phys->dirtStretch[j]=RandomFl(-0.5,0.5);
|
||
|
InstallCarAddOns(phys);
|
||
|
|
||
|
//if car is on left side, prepare for overtaking
|
||
|
//(otherwise ai players will immediatly try to change lanes, not a good idea).
|
||
|
if(i%2)
|
||
|
{
|
||
|
phys->overtaking=gCarEntities[0];
|
||
|
phys->overtakeSide=-1;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void InitGameEntities()
|
||
|
{
|
||
|
//initialize entity list
|
||
|
EntityResetCount();
|
||
|
gFirstEntity=(tGameEntity*)MemoryAllocateZeroedBlock(sizeof(tGameEntity));
|
||
|
gFirstEntity->next=gFirstEntity;
|
||
|
gFirstEntity->prev=gFirstEntity;
|
||
|
|
||
|
//process map info describtion
|
||
|
ProcessMapInfo();
|
||
|
|
||
|
//initialize car entities
|
||
|
InitCars();
|
||
|
|
||
|
//initialize camera
|
||
|
gCameraEntity=EntityNew(gFirstEntity);
|
||
|
|
||
|
//initialize ghost
|
||
|
if(gGameInfo->numLaps==-1)
|
||
|
{
|
||
|
gGhostEntity=EntityNew(gFirstEntity);
|
||
|
gGhostEntity->physics=MemoryAllocateZeroedBlock(sizeof(tCarPhysics));
|
||
|
MemoryMove(gGhostEntity->physics,gCarEntities[0]->physics,sizeof(tCarPhysics));
|
||
|
gGhostEntity->pos=Vector(10000,10000,10000);
|
||
|
gGhostEntity->physicsType=kPhysicsTypeGhost;
|
||
|
gGhostEntity->renderType=kRenderTypeGhost;
|
||
|
gGhostEntity->controlType=kControlTypeNone;
|
||
|
gGhostEntity->physicsData=gGameInfo->playerCars[0];
|
||
|
gGhostEntity->renderData=gCarEntities[0]->renderData;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void InitInfoDisplay();
|
||
|
|
||
|
//initialize a new game
|
||
|
int InitGame()
|
||
|
{
|
||
|
if(gFileTampered)
|
||
|
Exit();
|
||
|
|
||
|
//get map info data
|
||
|
gMapInfo=(tMapInfo*)FileGetParsedDataPtr(gGameInfo->map,kParserTypeMapInfoDesc,sizeof(tMapInfo));
|
||
|
|
||
|
//load enivronment describtion
|
||
|
LoadEnvironment(gGameInfo->environment);
|
||
|
|
||
|
//initialize fog
|
||
|
GLfloat fogColor[4];
|
||
|
*(tVector3*)fogColor=gEnvironment->fogColor;
|
||
|
fogColor[3]=1;
|
||
|
glFogfv(GL_FOG_COLOR,fogColor);
|
||
|
glFogf(GL_FOG_START,600);
|
||
|
glFogf(GL_FOG_END,800);
|
||
|
|
||
|
InitGameEntities();
|
||
|
|
||
|
//initialize game end flags
|
||
|
gInterfaceType=false;
|
||
|
gGameEnd=false;
|
||
|
gPaused=false;
|
||
|
gRaceFinished=false;
|
||
|
gDisqualified=false;
|
||
|
gLightning=false;
|
||
|
gInputEscMode=false;
|
||
|
gReplayViewedEntityID=gGameInfo->playerID;
|
||
|
gCameraMode=gConfig->cameraMode;
|
||
|
gCameraReverse=0;
|
||
|
gOutboxPos=0;
|
||
|
gGameChatMessage[0]='\0';
|
||
|
gGameChatMessageSize=0;
|
||
|
gNetPauseTime=0;
|
||
|
|
||
|
SoundSilence();
|
||
|
|
||
|
//reset replay log
|
||
|
LogReset();
|
||
|
GhostLogReset();
|
||
|
|
||
|
TracksClear();
|
||
|
ParticlesClear();
|
||
|
|
||
|
InitInfoDisplay();
|
||
|
|
||
|
//call once to reset stencil buffer
|
||
|
RenderStencilLayer(true,gConfig->stencil);
|
||
|
|
||
|
//initialze lighting
|
||
|
SetupLighting();
|
||
|
|
||
|
//render a frame to get graphics loaded
|
||
|
CalcCamera();
|
||
|
|
||
|
gClipEnable=false;
|
||
|
float time=TimeGetSeconds();
|
||
|
|
||
|
gNumGameChatMessages=0;
|
||
|
gEnableTextureLoad=false;
|
||
|
gNumTexturesRequested=0;
|
||
|
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);
|
||
|
gTexturesQualityModifier=gFileTable[i].tagged+1;
|
||
|
TexturesSelectTex(i);
|
||
|
SystemPoll(true);
|
||
|
}
|
||
|
}
|
||
|
gTexturesQualityModifier=0;
|
||
|
// PrintConsoleString("loading took: %f seconds.",TimeGetSeconds()-time);
|
||
|
gClipEnable=true;
|
||
|
|
||
|
//synchronize players on network
|
||
|
if(gGameInfo->network)
|
||
|
{
|
||
|
InterfaceDrawStrings("Waiting for other Players...","",kFileErr);
|
||
|
if(!NetworkSynch(gGameInfo->numNetPlayers))
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//start clock
|
||
|
gTimeStretch=1.0;
|
||
|
gBestLapTime=0;
|
||
|
StartFrameCount();
|
||
|
gPaused=false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void DisposeEntities()
|
||
|
{
|
||
|
if(gFirstEntity)
|
||
|
{
|
||
|
tGameEntity *entity=(tGameEntity*)gFirstEntity->next;
|
||
|
while(entity!=gFirstEntity)
|
||
|
{
|
||
|
tGameEntity *next=(tGameEntity*)entity->next;
|
||
|
if(entity->physics)
|
||
|
MemoryFreeBlock(entity->physics);
|
||
|
SoundFreeEntitySources(entity);
|
||
|
//FREE CAR PHYSICS!
|
||
|
MemoryFreeBlock(entity);
|
||
|
entity=next;
|
||
|
}
|
||
|
MemoryFreeBlock(gFirstEntity);
|
||
|
|
||
|
gFirstEntity=NULL;
|
||
|
gViewedEntity=NULL;
|
||
|
gCameraEntity=NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void StartReplay()
|
||
|
{
|
||
|
SoundSilence();
|
||
|
tCarPhysics physStore[kMaxPlayers];
|
||
|
|
||
|
// for(int i=0;i<gGameInfo->numPlayers;i++)
|
||
|
// physStore[i]=*(tCarPhysics*)gCarEntities[i]->physics;
|
||
|
|
||
|
DisposeEntities();
|
||
|
|
||
|
InitGameEntities();
|
||
|
|
||
|
/* for(int i=0;i<gGameInfo->numPlayers;i++)
|
||
|
{
|
||
|
*(tCarPhysics*)gCarEntities[i]->physics=physStore[i];
|
||
|
tCarPhysics *phys=(tCarPhysics*)gCarEntities[i]->physics;
|
||
|
phys->dirt=0;
|
||
|
for(int j=0;j<kMaxWheels;j++)
|
||
|
phys->wheels[j].lastTrack=0;
|
||
|
}*/
|
||
|
|
||
|
// for(int i=0;i<gNumGameChatMessages;i++)
|
||
|
// gGameChatMessagesRecv[i].frameCount-=gFrameCount;
|
||
|
|
||
|
gCameraEntity->pos=Vector(10000,10000,10000);
|
||
|
if(gCameraMode==kCameraFree)
|
||
|
gCameraMode=kCameraTripod;
|
||
|
if(gGameInfo->numLaps==-1)
|
||
|
gGhostEntity->pos=Vector(10000,10000,10000);
|
||
|
|
||
|
gFrameCount=gGameInfo->numLaps==-1?(gBestLapTime!=0?gBestLapStart+5:gCurrentLapStart+5):0;
|
||
|
gGraphFrameCount=gFrameCount;
|
||
|
gStartTime=TimeGetSeconds()-gFrameCount*kFrameTime;
|
||
|
gReplayIndex=0;
|
||
|
gReplayNextCam=gFrameCount+RandomFl(4,12)*kFPS;
|
||
|
|
||
|
TracksClear();
|
||
|
}
|
||
|
extern int gIndexPos;
|
||
|
extern int gGhostIndexPos;
|
||
|
|
||
|
void ReplayProcessNetwork(int *end)
|
||
|
{
|
||
|
if(gGameInfo->network)
|
||
|
{
|
||
|
tNetworkPacket message;
|
||
|
while(NetworkReceivePacket(&message))
|
||
|
switch(message.what)
|
||
|
{
|
||
|
case kMessageTypeEndReplay:
|
||
|
*end=true;
|
||
|
gGameEnd=kEndGameNoLeave;
|
||
|
break;
|
||
|
case kMessageTypeGameTerminated:
|
||
|
*end=true;
|
||
|
return;
|
||
|
case kMessageTypeChat:
|
||
|
InsertGameChatMessage(((tChatMessage*)message.data)->str);
|
||
|
ChatBufferInsert(((tChatMessage*)message.data),gChatBuffer);
|
||
|
PlayInterfaceSound(FileGetReference("chat.wav"));
|
||
|
break;
|
||
|
case kMessageTypeBye:
|
||
|
{
|
||
|
if(message.from==0)
|
||
|
sprintf(gDisconnectString,"%s quit and stopped hosting.",gGameInfo->playerNames[0]);
|
||
|
int netID=message.from;
|
||
|
int id=-1;
|
||
|
//find the players id
|
||
|
for(int i=0;i<gGameInfo->numNetPlayers;i++)
|
||
|
if(gGameInfo->netID[i]==netID)
|
||
|
id=i;
|
||
|
|
||
|
if(id!=-1)
|
||
|
{
|
||
|
tChatMessage m;
|
||
|
m.flags=kChatFlagSystem;
|
||
|
sprintf(m.str,"### %s is quitting.",gGameInfo->playerNames[id]);
|
||
|
SoundReInit();
|
||
|
PlayInterfaceSound(FileGetReference("chat.wav"));
|
||
|
InsertGameChatMessage(m.str);
|
||
|
ChatBufferInsert(&m,gChatBuffer);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case kMessageTypePlayerLeft:
|
||
|
{
|
||
|
int netID=message.from;
|
||
|
int id=-1;
|
||
|
//find the players id
|
||
|
for(int i=0;i<gGameInfo->numPlayers;i++)
|
||
|
if(gGameInfo->netID[i]==netID)
|
||
|
id=i;
|
||
|
if(id!=-1)
|
||
|
{
|
||
|
char leftMessage[256];
|
||
|
//PrintConsoleString("### Player %d left the game. netID: %d",id,netID);
|
||
|
sprintf(leftMessage,"### %s left the game.",gGameInfo->playerNames[id]);
|
||
|
InsertGameChatMessage(leftMessage);
|
||
|
//KillPlayer(id);
|
||
|
gGameInfo->netID[id]=-1;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int ReplayFrame()
|
||
|
{
|
||
|
int end=false;
|
||
|
static int save=false;
|
||
|
if(GetInterfaceKey(kInterfaceKeyEsc)&&!gGameInfo->network)
|
||
|
end=true;
|
||
|
if(GetInterfaceKey(kInterfaceKeyCmd)&&GetInterfaceKey(kInterfaceKeyOpt)&&GetInterfaceKey(kInterfaceKeyS)&&!gBackgroundReplay)
|
||
|
{
|
||
|
if(!save)
|
||
|
{
|
||
|
LogSaveToDisk();
|
||
|
save=true;
|
||
|
}
|
||
|
}
|
||
|
else save=false;
|
||
|
if(gGameEnd)
|
||
|
end=true;
|
||
|
ReplayProcessNetwork(&end);
|
||
|
if(gFrameCount>=gReplayOldFrameCount||gReplayIndex>=(gGameInfo->numLaps==-1?gGhostIndexPos:gIndexPos))
|
||
|
{
|
||
|
if(gMapInfo->reverse)
|
||
|
gGameInfo->reverse=!gGameInfo->reverse;
|
||
|
StartReplay();
|
||
|
}
|
||
|
if(gFrameCount>=gReplayNextCam&&gReplayAutoCam)
|
||
|
{
|
||
|
ParticlesClearScreen();
|
||
|
gCameraReverse=RandomProb(0.4);
|
||
|
gCameraMode=RandomProb(0.3)?kCameraTripod:RandomInt(kCameraChase,kCameraTop+1);
|
||
|
int nextViewID;
|
||
|
do{
|
||
|
nextViewID=RandomInt(0,gGameInfo->numPlayers);
|
||
|
}while(gGameInfo->netID[nextViewID]==-1);
|
||
|
tGameEntity *nextView=gCarEntities[nextViewID];
|
||
|
if(sqr(nextView->velo)>=1.0)
|
||
|
{
|
||
|
gViewedEntity=nextView;
|
||
|
gReplayViewedEntityID=nextViewID;
|
||
|
}
|
||
|
float cameraDuration;
|
||
|
switch(gCameraMode)
|
||
|
{
|
||
|
case kCameraChase:
|
||
|
case kCameraChaseClose:
|
||
|
cameraDuration=RandomFl(3,10);break;
|
||
|
case kCameraLeftSide:
|
||
|
case kCameraLeftWheel:
|
||
|
cameraDuration=RandomFl(2,5);break;
|
||
|
case kCameraTop:
|
||
|
cameraDuration=RandomFl(3,6);break;
|
||
|
case kCameraTripod:
|
||
|
cameraDuration=RandomFl(8,18);break;
|
||
|
case kCameraCockpit:
|
||
|
case kCameraCockpitCarHidden:
|
||
|
cameraDuration=RandomFl(2,5);
|
||
|
gCameraReverse=false;
|
||
|
break;
|
||
|
}
|
||
|
gReplayNextCam=gReplayNextCam+cameraDuration*kFPS;
|
||
|
}
|
||
|
|
||
|
while(!GameReplayFrame()&&gBackgroundReplay);
|
||
|
|
||
|
return end;
|
||
|
}
|
||
|
|
||
|
void RunReplay()
|
||
|
{
|
||
|
TextClearBufferFading();
|
||
|
//LogLoad(FileGetReference("test.log"),gGameInfo);
|
||
|
gReplay=true;
|
||
|
if(gGameInfo->numLaps==-1)
|
||
|
{
|
||
|
tCarPhysics *phys=(tCarPhysics*)gCarEntities[0]->physics;
|
||
|
if(phys->lapCount<=1)
|
||
|
LogToGhostLog();
|
||
|
}
|
||
|
gReplayOldFrameCount=(gGameInfo->numLaps==-1&&gBestLapTime!=0)?gBestLapTime+gBestLapStart:gFrameCount;
|
||
|
if(gReplayOldFrameCount<10)return;
|
||
|
LogSort();
|
||
|
//LogSaveToDisk();
|
||
|
gReplayAutoCam=true;
|
||
|
|
||
|
StartReplay();
|
||
|
while(!ReplayFrame());
|
||
|
|
||
|
if(gGameInfo->network&&gGameInfo->playerID==0)
|
||
|
{
|
||
|
NetworkSendPacket(kMessageTypeEndReplay,NULL,0,kMessagePriorityHigh,kMessageSendToAllButSelf);
|
||
|
}
|
||
|
// gReplay=false;
|
||
|
}
|
||
|
|
||
|
void ExitGame()
|
||
|
{
|
||
|
/* #ifndef __APPLE_CC__
|
||
|
#if __option(profile)
|
||
|
ProfilerDump("\pProfiler Dump");
|
||
|
#endif
|
||
|
#endif
|
||
|
*/
|
||
|
FFBStop();
|
||
|
UnPauseGame();
|
||
|
if(gGameInfo->network)
|
||
|
{
|
||
|
if(gGameInfo->playerID==0)
|
||
|
NetworkSendPacket(kMessageTypeEndGame,NULL,0,kMessagePriorityHigh,kMessageSendToAllButSelf);
|
||
|
else if(gGameEnd!=kEndGameNoLeave)
|
||
|
{
|
||
|
NetworkSendPacket(kMessageTypeBye,NULL,0,kMessagePriorityHigh,kMessageSendToAllButSelf);
|
||
|
NetworkSendPacket(kMessageTypeGameTerminated,NULL,0,kMessagePriorityHigh,gGameInfo->netID[gGameInfo->playerID]);
|
||
|
}
|
||
|
}
|
||
|
if((gGameEnd==kEndGameNoLeave||(gGameEnd==kEndGame&&!(gGameInfo->network&&gGameInfo->playerID!=0)))&&!gGameInfo->demolition)
|
||
|
{
|
||
|
gGameEnd=false;
|
||
|
while((GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter)||GetInterfaceKey(kInterfaceKeyEsc)));
|
||
|
RunReplay();
|
||
|
if(gGameInfo->network)
|
||
|
{
|
||
|
if(gGameInfo->playerID==0)
|
||
|
NetworkSendPacket(kMessageTypeEndGame,NULL,0,kMessagePriorityHigh,kMessageSendToAllButSelf);
|
||
|
else if(gGameEnd!=kEndGameNoLeave)
|
||
|
{
|
||
|
NetworkSendPacket(kMessageTypeBye,NULL,0,kMessagePriorityHigh,kMessageSendToAllButSelf);
|
||
|
NetworkSendPacket(kMessageTypeGameTerminated,NULL,0,kMessagePriorityHigh,gGameInfo->netID[gGameInfo->playerID]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* if(gGameEnd!=kEndGameRestart)
|
||
|
{
|
||
|
float startTime=TimeGetSeconds();
|
||
|
float t;
|
||
|
do{
|
||
|
t=TimeGetSeconds()-startTime;
|
||
|
RenderFrame(false);
|
||
|
InterfaceDrawBackgroundFade(t/0.3,true);
|
||
|
ScreenBlit();
|
||
|
}while(t<0.3);
|
||
|
}*/
|
||
|
|
||
|
DisposeEntities();
|
||
|
|
||
|
gInputChatMode=false;
|
||
|
gFrameCount=0x7fffffff;
|
||
|
TextClearBuffer();
|
||
|
TracksClear();
|
||
|
SoundSilence();
|
||
|
ParticlesClear();
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
gMapInfo=NULL;
|
||
|
gGameInfo=NULL;
|
||
|
gMapEnv=NULL;
|
||
|
TrackerLapTimeRegistryClose();
|
||
|
LoadEnvironment(FileGetReference("showroom.senv"));
|
||
|
FlushKeys();
|
||
|
}
|
||
|
|
||
|
int GetPlayerRanking()
|
||
|
{
|
||
|
tCarPhysics *phys=(tCarPhysics*)gCarEntities[gGameInfo->playerID]->physics;
|
||
|
if(phys->lapCount>gGameInfo->numLaps&&!gDisqualified)
|
||
|
{
|
||
|
int place=1;
|
||
|
for(int i=0;i<gGameInfo->numPlayers;i++)
|
||
|
{
|
||
|
tCarPhysics *phys2=(tCarPhysics*)gCarEntities[i]->physics;
|
||
|
if(phys2->lapCount>gGameInfo->numLaps)
|
||
|
if(phys2->lapTimes[gGameInfo->numLaps]<phys->lapTimes[gGameInfo->numLaps])
|
||
|
place++;
|
||
|
}
|
||
|
if(gGameInfo->maxTime)
|
||
|
return phys->lapTimes[gGameInfo->numLaps];
|
||
|
if(gGameInfo->numLaps==-1)
|
||
|
return gBestLapTime;
|
||
|
return place;
|
||
|
}
|
||
|
else
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int RunGame(tGameInfo *gInfo)
|
||
|
{
|
||
|
gReplay=false;
|
||
|
int place;
|
||
|
int reverse=gInfo->reverse;
|
||
|
do{
|
||
|
gGameInfo=gInfo;
|
||
|
if(InitGame())
|
||
|
while(!gGameEnd)
|
||
|
GameFrame();
|
||
|
place=GetPlayerRanking();
|
||
|
gInfo->reverse=reverse;
|
||
|
ExitGame();
|
||
|
gInfo->reverse=reverse;
|
||
|
}while(gGameEnd==kEndGameRestart);
|
||
|
gInterfaceGInfo=*gInfo;
|
||
|
StartBackgroundReplay();
|
||
|
return place;
|
||
|
}
|