2016-04-02 12:43:55 +00:00
|
|
|
#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 "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);
|
|
|
|
|
|
|
|
float velo=~entity->velo;
|
|
|
|
float driveSlip=0,slip=0,angularVelo=0;
|
|
|
|
int wheelsOnGround=0;
|
|
|
|
|
|
|
|
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(wheelsOnGround)
|
|
|
|
slip/=wheelsOnGround;
|
|
|
|
else
|
|
|
|
slip=0;
|
|
|
|
CalcThrottleBrake(car,phys,driveSlip,angularVelo,velo,slip);
|
|
|
|
CalcSteering(entity,car,phys,velo);
|
2016-04-02 13:19:10 +00:00
|
|
|
|
2016-04-02 12:43:55 +00:00
|
|
|
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(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;
|
|
|
|
}
|
|
|
|
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(GetButtonInput(kInputHorn))
|
|
|
|
phys->lightFlags|=kLightFlagHorn;
|
|
|
|
else
|
|
|
|
phys->lightFlags&=~kLightFlagHorn;
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|