#include <stdio.h>
#include <string.h>
#include <math.h>
#include "entities.h"
#include "gameframe.h"
#include "carphysics.h"
#include "controls.h"
#include "config.h"
#include "renderframe.h"
#include "gameinitexit.h"
#include "particles.h"
#include "gametime.h"
#include "network.h"
#include "random.h"
#include "reg_tool_3.h"
#include "rt3_redline.h"
#include "initexit.h"
#include "text.h"

#define kThrottleTime 0.3
#define kThrottleReleaseTime 0.2
#define kThrottleTCRReleaseTime 0.7
#define kThrottleTimeSpinning 0.6
#define kBrakeTime 0.4
#define kBrakeReleaseTime 0.2
#define kSteerReleaseTime 0.6
#define kVeloSteerReleaseTime 0
//#define kSteerTime 1.2
#define kSteerTime 0.6
#define kVeloSteerTime 0.05
#define kHandbrakeTime 0.2
#define kHandbrakeReleaseTime 0.01

#define sign(x) ((x)<0?-1:1)

#define kMaxThottleSlip 0.033
#define kMinSpinAngularVelo (4*PI)
#define kMaxBrakeSlip 0.05

int gGearUpPress=false;
int gGearDownPress=false;
int gLightPress=false;
int gCameraPress=false;
int gReplayCameraPress=false;
int gTauntPress=false;
int gArrowPress=false;
int gEscPress=false;
int gPausePress=false;

float gSteerAxis=0;
float gThrottleAxis=0;
int gAxisSteering=false;
int gAxisThrottleBrake=false;
int gInputChatMode=false;
int gInputEscMode=kInputEscModeNone;
int gInputEscSelection;
int gGameChatMessageSize=0;

#define kMaxGameChatMessageSize 128
char gGameChatMessage[kMaxGameChatMessageSize]="";

void ButtonThrottle(tCarDefinition *car,tCarPhysics *phys,float driveSlip,float angularVelo,float velo,float throttleInput,int tcr)
{
	float maxSlip=velo<20?0.2-velo/20*(0.2-kMaxThottleSlip):kMaxThottleSlip;
	if(throttleInput<0)
		throttleInput=0;
	if(throttleInput>phys->throttle){
		if(driveSlip*sign(phys->gear)<maxSlip||fabs(angularVelo)<kMinSpinAngularVelo||!tcr||(phys->clutch<1&&phys->rpm>car->clutchRPM))
		{
			phys->throttle+=kFrameTime*(1/kThrottleTime);
			if(throttleInput>phys->throttle)
				throttleInput=phys->throttle;
		}
		else 
		{
			phys->throttle-=kFrameTime*(1/kThrottleTCRReleaseTime);
			if(throttleInput<phys->throttle)
				throttleInput=phys->throttle;
		}
	}
	else {
		phys->throttle-=kFrameTime*(1/kThrottleReleaseTime);
		if(throttleInput<phys->throttle)
			throttleInput=phys->throttle;
	}

	if(phys->throttle>1)
		phys->throttle=1;
	else if(phys->throttle<phys->idleThrottle&&phys->rpm<=car->idleRPM)
		phys->throttle=phys->idleThrottle;

	phys->clutch=1;
}


void ButtonBrake(tCarPhysics *phys,float slip,float angularVelo,float brakeInput,int als)
{
	if(brakeInput>1)
		brakeInput=1;
	else if(brakeInput<0)
		brakeInput=0;

	if(brakeInput<0)
		brakeInput=0;
	if(brakeInput>phys->brake)
	{
		if((-slip*sign(angularVelo)<kMaxBrakeSlip)||(phys->brake<0.1)||!als)
			phys->brake+=kFrameTime*(1/kBrakeTime);
		else
			phys->brake-=kFrameTime*(1/kBrakeTime);
			
		phys->arcadeBrake+=kFrameTime*(1/kBrakeTime);
		
		if(brakeInput<phys->brake)
			phys->brake=brakeInput;
		if(brakeInput<phys->arcadeBrake)
			phys->arcadeBrake=brakeInput;
	}	
	else
	{
		phys->brake-=kFrameTime*(1/kBrakeReleaseTime);

		phys->arcadeBrake-=kFrameTime*(1/kBrakeReleaseTime);

		if(brakeInput>phys->brake)
			phys->brake=brakeInput;
		if(brakeInput>phys->arcadeBrake)
			phys->arcadeBrake=brakeInput;
	}	
}

void CalcThrottleBrake(tCarDefinition *car,tCarPhysics *phys,float driveSlip,float angularVelo,float velo,float slip)
{
	if(car->clutchRPM==0)
		car->clutchRPM=3000;
	int raceOver=(phys->lapCount>gGameInfo->numLaps&&gGameInfo->numLaps!=-1);
	if(!raceOver)
	{
		float gas,brake,gasbrake;
		if(gConfig->seperateGasBrake)
		{
			if(gConfig->reverseGas)
			{
				gas=GetAxisInput(kInputThrottleAxis);
				brake=GetAxisInput(kInputBrakeAxis);
			}
			else
			{
				gas=1-GetAxisInput(kInputThrottleAxis);
				brake=1-GetAxisInput(kInputBrakeAxis);
			}
			gasbrake=gas-brake;
		}
		else
		{
			gasbrake=GetAxisInput(kInputThrottleBrakeAxis);
			if(gConfig->reverseGas)
				gasbrake=-gasbrake;
			gas=gasbrake;
			brake=-gasbrake;
		}
		
		if(gAxisThrottleBrake)
		{
			
			if(gConfig->automatic&&phys->gear==-1)
			{
				ButtonBrake(phys,slip,angularVelo,gas,true);
				ButtonThrottle(car,phys,driveSlip,angularVelo,velo,brake,(brake<0.95)&&!gConfig->disableAnalogueTCS);
			}
			else
			{
				ButtonBrake(phys,slip,angularVelo,brake,true);
				ButtonThrottle(car,phys,driveSlip,angularVelo,velo,gas,(gas<0.95)&&!gConfig->disableAnalogueTCS);
			}
			if(GetButtonInput(kInputKickdownButton)||GetButtonInput(kInputBrakeButton)||GetButtonInput(kInputGasButton))
				gAxisThrottleBrake=false;
		}
		else
		{
			int brake=GetButtonInput(kInputBrakeButton);
			int gas=GetButtonInput(kInputGasButton);
			int kickdown=GetButtonInput(kInputKickdownButton);

			int gasInput=(gConfig->automatic?(phys->gear>=0?gas||kickdown:brake):(gas||kickdown))?1:0;
			ButtonThrottle(car,phys,driveSlip,angularVelo,velo,gasInput,!kickdown);
			int brakeInput=(gConfig->automatic?(phys->gear>=0?brake:gas||kickdown):brake)?1:0;
			ButtonBrake(phys,slip,angularVelo,brakeInput,true);
			
			if(gThrottleAxis!=gasbrake)
				gAxisThrottleBrake=true;		
		}
		gThrottleAxis=gasbrake;
	}
	else
	{
		ButtonBrake(phys,slip,angularVelo,1,true);
		ButtonThrottle(car,phys,driveSlip,angularVelo,velo,0,true);
	}
}

void ButtonSteering(tGameEntity *entity,tCarDefinition *car,tCarPhysics *phys,float velo,float input)
{
	if(input>1) input=1;
	else if(input<-1) input=-1;

	tVector3 carDir=!Vector(MatrixGetZVector(entity->dir)->x,0,MatrixGetZVector(entity->dir)->z);
	tVector3 veloDir=!Vector(entity->velo.x,0,entity->velo.z);
	float angleSin=(veloDir%carDir).y;
	if(fabs(angleSin)>1.0)
		angleSin=sign(angleSin);
	float angle=-asin(angleSin);
	float optimalSteering=angle/car->wheels[0].maxAngle;
	if(velo<1)
		optimalSteering=0;

	if(input>phys->steering)
	{
		float steerSpeed=(phys->steering<0)?(1/(kSteerReleaseTime+kVeloSteerReleaseTime*velo)) :(1/(kSteerTime+kVeloSteerTime*velo));
		if(phys->steering<optimalSteering)
			steerSpeed*=1+(optimalSteering-phys->steering)*4;
		if(gGameInfo->arcade==kGameModeTurbo)
			steerSpeed*=2;
		phys->steering+=kFrameTime*steerSpeed;
		
		if(input<phys->steering)
			phys->steering=input;
	}
	else if(input<phys->steering)
	{
		float steerSpeed=(phys->steering>0)?(1/(kSteerReleaseTime+kVeloSteerReleaseTime*velo)) :(1/(kSteerTime+kVeloSteerTime*velo));
		if(phys->steering>optimalSteering)
			steerSpeed*=1+(phys->steering-optimalSteering)*4;
		if(gGameInfo->arcade==kGameModeTurbo)
			steerSpeed*=2;
		phys->steering-=kFrameTime*steerSpeed;
		
		if(input>phys->steering)
			phys->steering=input;
	}		
}

void CalcSteering(tGameEntity *entity,tCarDefinition *car,tCarPhysics *phys,float velo)
{
	if(gAxisSteering)
	{
		gSteerAxis=GetAxisInput(kInputSteerAxis);
		float ax3=gSteerAxis*gSteerAxis*gSteerAxis;
		float ax=0.3*gSteerAxis+0.7*ax3;
		ButtonSteering(entity,car,phys,velo,ax);

		if(GetButtonInput(kInputSteerLeftButton)||GetButtonInput(kInputSteerRightButton))
			gAxisSteering=false;
	}
	else
	{
		float input=0;
		int l=GetButtonInput(kInputSteerLeftButton);
		int r=GetButtonInput(kInputSteerRightButton);
		if(l&&r)
			input=phys->steering;
		else if(l)
			input=1;
		else if(r)
			input=-1;
		ButtonSteering(entity,car,phys,velo,input);
		if(gSteerAxis!=GetAxisInput(kInputSteerAxis))
			gAxisSteering=true;	
	}
}

typedef struct{
	char *name;
	int numCopies;
}tRegData;

void ControlEntityUserInput(tGameEntity *entity)
{
	if(entity->physicsType!=kPhysicsTypeCar)
		return;
	tCarPhysics *phys=(tCarPhysics*)entity->physics;
	tCarDefinition *car=&(phys->car);

	int isValid=true;
	float velo=~entity->velo;
	float driveSlip=0,slip=0,angularVelo=0;
	int wheelsOnGround=0;
	int valid=true;
	if((car->demoAvailable-car->numColors!=1)&&(entity==gCarEntities[gGameInfo->playerID]))
		isValid=false;
		
	for(int i=0;i<car->numWheels;i++)
	{
		if(phys->wheels[i].onGround)
		{
			driveSlip+=phys->wheels[i].slip*car->wheels[i].powered;
			slip+=phys->wheels[i].slip;
			wheelsOnGround++;
		}
		angularVelo+=phys->wheels[i].angularVelo*car->wheels[i].powered;
	}
	if((gMapInfo->demoAvailable+gMapInfo->numObjs))
		isValid=false;
		
	if(wheelsOnGround)
		slip/=wheelsOnGround;
	else
		slip=0;
	CalcThrottleBrake(car,phys,driveSlip,angularVelo,velo,slip);
	CalcSteering(entity,car,phys,velo);
	
	if(!isValid)
		if(entity->regData)
			qRT3_LicenseTestApp2(phys->regCode,((tRegData*)(entity->regData))->name,((tRegData*)(entity->regData))->numCopies,isValid);
	
	if(GetButtonInput(kInputHandbrakeButton))
		phys->handbrake+=kFrameTime*(1/kHandbrakeTime);
	else
		phys->handbrake-=kFrameTime*(1/kHandbrakeReleaseTime);
	if(phys->handbrake>1)
		phys->handbrake=1;
	else if(phys->handbrake<0)
		phys->handbrake=0;

	if(!isValid)
		if(entity->regData)
			qRT3_LicenseTestBlock2(phys->regCode,((tRegData*)(entity->regData))->name,((tRegData*)(entity->regData))->numCopies,isValid);

	if(gFrameCount*kFrameTime>=kStartGameDelaySeconds)
	{
		if(gConfig->automatic)
		{
			if((gFrameCount-1)*kFrameTime>phys->lastGearSwitch+car->gearSwitchTime)
			{
				if(phys->gear>=1)
				{
					int shiftUp=false;
					if(car->shiftUpRPMFix)
						shiftUp=phys->rpm>car->shiftUpRPMFix;
					else
						shiftUp=phys->rpm>car->maxRPM;
					
					if(shiftUp&&phys->gear<car->numGears-2)
					{
						if(!GetButtonInput(kInputKickdownButton)&&phys->gear>0&&gFrameCount*kFrameTime>=kStartGameDelaySeconds+1)
						{
							phys->lastGear=phys->gear;
							phys->gear++;
							phys->lastGearSwitch=gFrameCount*kFrameTime;
							if(gGameInfo->arcade==kGameModeTurbo)
								phys->lastGearSwitch-=car->gearSwitchTime*0.5;
						}
					}	
					else if(phys->rpm<car->shiftDownRPM&&phys->gear>1)
					{
						phys->lastGear=phys->gear;
						phys->gear--;
						phys->lastGearSwitch=gFrameCount*kFrameTime;
						if(gGameInfo->arcade==kGameModeTurbo)
							phys->lastGearSwitch-=car->gearSwitchTime*0.5;
					}	
				}
				
				if(phys->gear==0||velo<1)
				{
					if(phys->gear<1&&((GetButtonInput(kInputKickdownButton)||GetButtonInput(kInputGasButton)))||(gAxisThrottleBrake&&gThrottleAxis>0))
					{
						phys->lastGear=phys->gear;
						phys->gear=1;
						phys->lastGearSwitch=gFrameCount*kFrameTime;
					}	
					else if(phys->gear>=0&&GetButtonInput(kInputBrakeButton)||(gAxisThrottleBrake&&gThrottleAxis<0))
					{
						phys->lastGear=phys->gear;
						phys->gear=-1;
						phys->lastGearSwitch=gFrameCount*kFrameTime;
					}					
				}
			}
		}
		else
		{
			if(GetButtonInput(kInputGearUp)){
				if(phys->gear<car->numGears-2&&!gGearUpPress){
					phys->lastGear=phys->gear;
					phys->gear++;
					gGearUpPress=true;
					phys->lastGearSwitch=gFrameCount*kFrameTime;
					if(gGameInfo->arcade==kGameModeTurbo)
						phys->lastGearSwitch-=car->gearSwitchTime*0.5;
				}
			}
			else gGearUpPress=false;
			
			if(GetButtonInput(kInputGearDown)){
				if(phys->gear>-1&&!gGearDownPress){
					phys->lastGear=phys->gear;
					phys->gear--;
					gGearDownPress=true;
					phys->lastGearSwitch=gFrameCount*kFrameTime;
					if(gGameInfo->arcade==kGameModeTurbo)
						phys->lastGearSwitch-=car->gearSwitchTime*0.5;
				}
			}
			else gGearDownPress=false;	
		}
		
		float gearSwitchTime=phys->gear<=1?0.3:car->gearSwitchTime;
		if(gFrameCount*kFrameTime<phys->lastGearSwitch+gearSwitchTime)
		{
			float switchTime=(gFrameCount*kFrameTime-phys->lastGearSwitch)/gearSwitchTime;
			phys->clutch=switchTime;
			if(phys->rpm<car->clutchRPM)
				phys->clutch=(phys->rpm-car->idleRPM*1.5)/(car->clutchRPM-car->idleRPM*1.5);
			if(switchTime<0.5&&phys->gear>1)
				if(phys->lastGear>phys->gear)
					phys->throttle=0.7;
				else
					phys->throttle=phys->idleThrottle;
			if(entity==gViewedEntity)
			{	
				int invalid=false;
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_CODE_01,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_CODE_02,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_03,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_04,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_05,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_06,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_07,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_08,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_09,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_10,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_11,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_12,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_13,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_14,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_15,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_16,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_17,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_18,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_19,invalid);
				if(!invalid)qRT3_LicenseIsSameCode(phys->regCode,RT3_PIRATED_FAKE_20,invalid);
				valid=!invalid;
			}
		}
		else
			if(phys->rpm<car->clutchRPM)
				phys->clutch=(phys->rpm-car->idleRPM*1.5)/(car->clutchRPM-car->idleRPM*1.5);
			else 
				phys->clutch=1;
				
		if(phys->clutch<0)
			phys->clutch=0;
	}	
	
	if(!isValid)
		if(gFrameCount>kFPS*30)
			phys->throttle=0;

	if(GetButtonInput(kInputHorn))
		phys->lightFlags|=kLightFlagHorn;
	else
		phys->lightFlags&=~kLightFlagHorn;	

	if(!valid)
		if(RandomProb(kFrameTime/car->gearSwitchTime*7))
			phys->gear=0;
	
	if(GetButtonInput(kInputLeftIndicator))
		phys->lightFlags|=kLightFlagLIndLight;	
	else if(GetButtonInput(kInputRightIndicator))
		phys->lightFlags|=kLightFlagRIndLight;
	else 
		phys->lightFlags&=~(kLightFlagLIndLight+kLightFlagRIndLight);	
		
	if(GetButtonInput(kInputLightButton)){	
		if(!gLightPress)
		{
			gLightPress=true;
			phys->lightFlags^=kLightFlagDriveLight;
		}
	}else gLightPress=false;	
}

void ControlEntityAIInput(tGameEntity *entity);

extern float gEscDisplay;

void HandleEscModeInput()
{
	if(GetInterfaceKey(kInterfaceKeyEsc)||GetInterfaceKey(kInterfaceKeyDelete))
	{
		if(!gEscPress)
		{
			gInputEscMode=kInputEscModeNone;
			gEscPress=true;
			if(!gGameInfo->network)
				UnPauseGame();
		}
	}
	else
		gEscPress=false;
	if(GetInterfaceKey(kInterfaceKeyDown))
	{
		if(!gArrowPress)
		{
			gInputEscSelection--;
			if(gInputEscSelection<0)
				gInputEscSelection=(gGameInfo->network?1:2);
			gArrowPress=true;
		}
	}
	else if(GetInterfaceKey(kInterfaceKeyUp))
	{
		if(!gArrowPress)
		{
			gInputEscSelection=(gInputEscSelection+1)%(gGameInfo->network?2:3);
			gArrowPress=true;
		}
	}
	else
		gArrowPress=false;
	if(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter))
	{
		if(gInputEscSelection==1)
			if(gInputEscMode==kInputEscModeQuit)
				Exit();
			else
				gGameEnd=kEndGame;
		if(gInputEscSelection==2)
			gGameEnd=kEndGameRestart;
		if(gInputEscMode==kInputEscModeQuit)
			gEscDisplay=0;
		gInputEscMode=kInputEscModeNone;
		if(!gGameInfo->network)
			UnPauseGame();
	}
}

void HandleChatModeInput()
{
	while(char ch=GetKeyInput(NULL))
	{
		if(ch=='\r')
		{
			if(ch=='\r'&&strlen(gGameChatMessage)>0)
			{
				tChatMessage msg;
				memset((void*)&msg,0,sizeof(tChatMessage));
				sprintf(msg.str,"%s: \255#a\255%s",gConfig->playerName,gGameChatMessage);
				msg.flags=0;
				NetworkSendPacket(kMessageTypeChat,&msg,sizeof(tChatMessage),kMessagePriorityHigh,kMessageSendToAll);					
			}				
			gGameChatMessage[0]='\0';
			gGameChatMessageSize=0;
			gInputChatMode=false;
		}
		if((ch==0x7f||ch==0x08)&&gGameChatMessageSize>0)
			gGameChatMessage[--gGameChatMessageSize]='\0';			
		if(ch>=' '&&ch<='z'&&gGameChatMessageSize<kMaxGameChatMessageSize-1)
		{
			gGameChatMessage[gGameChatMessageSize++]=ch;
			gGameChatMessage[gGameChatMessageSize]='\0';
		}
	}
}

void HandleNetworkInput()
{
	if(GetButtonInput(kInputChat))
	{
		gInputChatMode=true;
		FlushKeys();
	}

	int tauntPress=false;
	for(int i=kInputTaunt1;i<=kInputTaunt5;i++)
		if(GetButtonInput(i))
		{
			tauntPress=true;
			if(!gTauntPress&&*gConfig->taunts[i-kInputTaunt1])
			{
				tChatMessage msg;
				memset((void*)&msg,0,sizeof(tChatMessage));
				snprintf(msg.str,256,"%s: \255#a\255%s",gConfig->playerName,gConfig->taunts[i-kInputTaunt1]);
				msg.flags=0;
				NetworkSendPacket(kMessageTypeChat,&msg,sizeof(tChatMessage),kMessagePriorityHigh,kMessageSendToAll);					
			}
		}				
	gTauntPress=tauntPress;
	
					
	if(gInputChatMode) 
		HandleChatModeInput();
}

void HandleGameInput()
{
	tCarPhysics *phys=(tCarPhysics*)gCarEntities[gGameInfo->playerID]->physics;	

	if(GetButtonInput(kInputCamera))
	{
		if(!gCameraPress)
		{
			ParticlesClearScreen();
			gCameraMode=(++gCameraMode)%(gConfig->allCams||gReplay||phys->lapCount>gGameInfo->numLaps&&gGameInfo->numLaps!=-1?kCameraNumModes:kCameraLeftWheel);
			gReplayAutoCam=false;			
		}	
		gCameraPress++;
		if(gCameraPress>=kFPS&&gCameraMode!=kCameraFree)
		{
			gCameraMode=kCameraFree;
			TextPrintfToBufferFormatedFading(Vector(0,1),0.03,kTextAlignMiddle,1,2,"freecam mode.");
		}
	}
	else gCameraPress=0;

	if(GetButtonInput(kInputCameraChangeCar)){
		if(!gReplayCameraPress)
		{
			if(gReplay||phys->lapCount>gGameInfo->numLaps)
			{
				do{
					gReplayViewedEntityID=(gReplayViewedEntityID+1)%gGameInfo->numPlayers;
				}while(gGameInfo->netID[gReplayViewedEntityID]==-1&&gGameInfo->network);
				if(gReplay)
					gReplayAutoCam=false;		
				gReplayCameraPress=true;
			}
		}
	}else
		gReplayCameraPress=false;
	
	if(gReplay&&!gGameInfo->network)
	{
		float oldStretch=gTimeStretch;
		if(GetButtonInput(kInputChat))
			gTimeStretch=0.25;
		else
			gTimeStretch=1.0;
		if(gTimeStretch!=oldStretch)
		{
			float curTime=gStartTime+(gFrameCount*kFrameTime)/oldStretch;
			gStartTime=curTime-(gFrameCount*kFrameTime)/gTimeStretch;
		}
	}	
	gCameraReverse=GetButtonInput(kInputCameraReverse);


	
	if(GetButtonInput(kInputPause)&&!gReplay&&!gPaused&&!gPausePress)
	{
		if(!gGameInfo->network)
			PauseGame();
		else
		{
			int pauseFrameCount=gFrameCount+kFPS*0.5;
			S32Swap(pauseFrameCount);
			NetworkSendPacket(kMessageTypePause,&pauseFrameCount,sizeof(int),kMessagePriorityHigh,kMessageSendToAll);
		}
		gPausePress=true;
	}
			
	if(((GetButtonInput(kInputPause)&&!gPausePress))&&gPaused&&!gInputChatMode)
	{
		if(!gGameInfo->network)
			UnPauseGame();
		else
			NetworkSendPacket(kMessageTypeResume,NULL,0,kMessagePriorityHigh,kMessageSendToAll);
		gPausePress=true;
	}
	
	if(!GetButtonInput(kInputPause))
		gPausePress=false;

	if(gGameInfo->network)
		HandleNetworkInput();
	
/*	if(GetInterfaceKey(kInterfaceKeyCmd)&&GetInterfaceKey(kInterfaceKeyQ))
	{
		gInputEscMode=kInputEscModeQuit;
		gInputEscSelection=1;
		if(!gGameInfo->network)
			PauseGame();
	}*/	

	if(GetInterfaceKey(kInterfaceKeyEsc))//||(GetInterfaceKey(kInterfaceKeyDelete)&&!gInputChatMode))
	{
		if(gInputChatMode)
		{
			gGameChatMessage[0]='\0';
			gGameChatMessageSize=0;
			gInputChatMode=false;
			gEscPress=true;
		}
		else if(!gEscPress)
//			if(!gGameInfo->network&&((phys->lapCount>gGameInfo->numLaps&&gGameInfo->numLaps!=-1)||(gFrameCount*kFrameTime-kStartGameDelaySeconds>gGameInfo->maxTime&&gGameInfo->maxTime>0)))
			if((gReplay||((phys->lapCount>gGameInfo->numLaps&&gGameInfo->numLaps!=-1)))&&(!gGameInfo->network||gGameInfo->playerID==0))//||(gFrameCount*kFrameTime-kStartGameDelaySeconds>gGameInfo->maxTime&&gGameInfo->maxTime>0)))
				gGameEnd=kEndGame;
			else
			{
				gEscPress=true;
				gInputEscMode=kInputEscModeNormal;
				gInputEscSelection=1;
				if(!gGameInfo->network)
					PauseGame();
			}
	}
	else
		gEscPress=false;
}

void ControlFrame()
{	
	if(!gPaused&&!gReplay)
	{
		tGameEntity *entity=(tGameEntity*)gFirstEntity->next;
		while(entity!=gFirstEntity)
		{
			if(entity->physicsMachine==kPhysicsLocal)
			{
				switch(entity->controlType)
				{
					case kControlTypeUserInput:
						ControlEntityUserInput(entity);
						break;
					case kControlTypeAIInput:
						ControlEntityAIInput(entity);
						break;					
				}
			}
			entity=(tGameEntity*)entity->next;
		}
	}

	if(!gInputEscMode)
		HandleGameInput();
	else
		HandleEscModeInput();
}