work on CAutomobile

This commit is contained in:
aap 2021-08-16 00:19:09 +02:00
parent 39d2c427e5
commit 2f92ccecb1
11 changed files with 218 additions and 127 deletions

View file

@ -140,7 +140,7 @@ class CPad
public:
enum
{
HORNHISTORY_SIZE = 5,
HORNHISTORY_SIZE = 8,
DRUNK_STEERING_BUFFER_SIZE = 10,
};
CControllerState NewState;

View file

@ -95,6 +95,7 @@ bool gUseModelResources;
bool gUseResources;
bool gNASTY_NASTY_MEM_SHUTDOWN_HACK; // rather unused
bool gbPreviewCity; // don't do worldstream-style rendering but traditional method
bool gMultiplayerSuperBrakeOnPause = true;
float FramesPerSecond = 30.0f;

View file

@ -43,6 +43,7 @@ extern bool gUseModelResources;
extern bool gUseResources;
extern bool gNASTY_NASTY_MEM_SHUTDOWN_HACK;
extern bool gbPreviewCity;
extern bool gMultiplayerSuperBrakeOnPause;
class CSprite2d;

View file

@ -22,7 +22,7 @@ public:
z = v.z;
}
// (0,1,0) means no rotation. So get right vector and its atan
float Heading(void) const { return Atan2(-x, y); }
float Heading(void) const { return x == 0.0f && y == 0.0f ? 0.0f : Atan2(-x, y); }
float Magnitude(void) const { return Sqrt(x*x + y*y + z*z); }
float MagnitudeSqr(void) const { return x*x + y*y + z*z; }
float Magnitude2D(void) const { return Sqrt(x*x + y*y); }

View file

@ -1090,15 +1090,18 @@ enum
MI_LAST_VEHICLE = MI_VCNMAV,
// these indices are sort of original
// with these three i don't know which is which:
MI_RCBARON = -999,
// with these two i don't know which is which:
MI_CADDY = -963,
MI_BAGGAGE = -955,
MI_BAGGAGE = -999,
MI_RCBARON = -955,
MI_COMET = -972, // ps2 CAutomobile::IsOpenTopCar
MI_SANDKING = -981, // ps2 CAutomobile::ProcessControl
MI_VOODOO = -984, // ps2 hydraulics
MI_SEASPAR = -986,
MI_SPARROW = -985,
// HACK HACK, hopefully temporary
MI_SEASPAR = -2000,
MI_SPARROW,
MI_FBIRANCH,
MI_FBIRANCH = -2000,
MI_VICECHEE,
MI_RIO,
MI_SQUALO,
@ -1108,11 +1111,8 @@ enum
MI_MARQUIS,
MI_SKIMMER,
MI_TROPIC,
MI_SANDKING,
MI_VOODOO,
MI_CUBAN,
MI_PHEONIX,
MI_COMET,
MI_SABRE,
MI_VIRGO,
MI_RANCHER,

View file

@ -428,7 +428,8 @@ enum PedState
PED_EXIT_CAR,
PED_HANDS_UP,
PED_ARRESTED,
PED_DEPLOY_STINGER
PED_DEPLOY_STINGER,
PED_STATE64
};
enum eMoveState {

View file

@ -86,6 +86,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
switch(GetModelIndex()){
case MI_HUNTER:
case MI_ANGEL:
case MI_ANGEL2:
case MI_FREEWAY:
m_nRadioStation = V_ROCK;
break;
@ -150,8 +151,8 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
for(i = 0; i < 6; i++)
m_randomValues[i] = CGeneral::GetRandomNumberInRange(-0.15f, 0.15f);
m_fMass = pHandling->fMass;
m_fTurnMass = pHandling->fTurnMass;
m_fMass = pHandling->GetMass();
m_fTurnMass = pHandling->GetTurnMass();
m_vecCentreOfMass = pHandling->CentreOfMass;
m_fAirResistance = pHandling->fDragMult > 0.01f ? pHandling->fDragMult*0.0005f : pHandling->fDragMult;
m_fElasticity = 0.05f;
@ -201,6 +202,10 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_nNumPassengers = 0;
m_pBombRigger = nil;
m_bombType = CARBOMB_NONE;
bUnknownFlag = false;
if(m_nDoorLock == CARLOCK_UNLOCKED &&
(id == MI_POLICE || id == MI_ENFORCER || id == MI_RHINO))
m_nDoorLock = CARLOCK_LOCKED_INITIALLY;
@ -231,6 +236,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
bExplosionProof = true;
bBulletProof = true;
}
m_vehLCS_2A3 = -1;
}
void
@ -242,6 +248,9 @@ CAutomobile::SetModelIndex(uint32 id)
#define SAND_SLOWDOWN (0.01f)
float CAR_BALANCE_MULT = 0.3f;
float CAR_INAIR_ROTF = 0.0007f;
float CAR_INAIR_ROTLIM = 0.02f;
float HELI_ROTOR_DOTPROD_LIMIT = 0.95f;
CVector vecSeaSparrowGunPos(-0.5f, 2.4f, -0.785f);
CVector vecHunterGunPos(0.0f, 4.8f, -1.3f);
CVector vecHunterRocketPos(2.5f, 1.0f, -0.5f);
@ -253,15 +262,28 @@ CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f);
void
CAutomobile::ProcessControl(void)
{
// TODO(LCS):
// TheCamera can remove service vehicles
// some audio (?) stuff
int i;
float wheelRot;
CColModel *colModel;
float brake = 0.0f;
if(TheCamera.WorldViewerBeingUsed){
if(bIsAmbulanceOnDuty){
bIsAmbulanceOnDuty = false;
CCarCtrl::NumAmbulancesOnDuty--;
}
if(bIsFireTruckOnDuty){
bIsFireTruckOnDuty = false;
CCarCtrl::NumFiretrucksOnDuty--;
}
}
if(m_vehLCS_2A3 >= 0){
m_vehLCS_2A4--;
if(m_vehLCS_2A4 == 0)
m_vehLCS_2A3 = -1;
}
if(bUsingSpecialColModel)
colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
else
@ -320,7 +342,7 @@ CAutomobile::ProcessControl(void)
ScanForCrimes();
}
// TODO(LCS): the fields used by this function are weird
// TODO(LCS)? re-inline this and change where bDriverLastFrame is set
ActivateBombWhenEntered();
// Process driver
@ -394,7 +416,7 @@ CAutomobile::ProcessControl(void)
case STATUS_PLAYER:
if(playerRemote ||
// TODO(LCS): ped state 64
pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR && pDriver->GetPedState() != PED_ARRESTED){
pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR && pDriver->GetPedState() != PED_ARRESTED && pDriver->GetPedState() != PED_STATE64){
// process control input if controlled by player
if(playerRemote || pDriver->m_nPedType == PEDTYPE_PLAYER1)
ProcessControlInputs(0);
@ -419,7 +441,33 @@ CAutomobile::ProcessControl(void)
}else
m_vecCentreOfMass.z = pHandling->CentreOfMass.z;
// TODO(LCS): some in air handling?
// in air handling
if(m_nWheelsOnGround == 0 &&
GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE && GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI){
float turnForce = m_fTurnMass * CAR_INAIR_ROTF;
turnForce *= Min(3000.0f/m_fTurnMass, 1.0f);
if(CPad::GetPad(0)->GetHandBrake()){
float upRot = DotProduct(m_vecTurnSpeed, GetUp());
if(upRot < CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() < 0.0f ||
upRot > -CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() > 0.0f)
ApplyTurnForce(GetRight() * turnForce * (CPad::GetPad(0)->GetSteeringLeftRight()/128.0f) * CTimer::GetTimeStep(),
m_vecCentreOfMass + GetForward());
}else if(!CPad::GetPad(0)->GetAccelerate()){
float fwdRot = DotProduct(m_vecTurnSpeed, GetForward());
if(fwdRot < CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() < 0.0f ||
fwdRot > -CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() > 0.0f)
ApplyTurnForce(GetRight() * turnForce * (CPad::GetPad(0)->GetSteeringLeftRight()/128.0f) * CTimer::GetTimeStep(),
m_vecCentreOfMass + GetUp());
}
if(!CPad::GetPad(0)->GetAccelerate()){
float rightRot = DotProduct(m_vecTurnSpeed, GetRight());
if(rightRot < CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringUpDown() < 0.0f ||
rightRot > -CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringUpDown() > 0.0f)
ApplyTurnForce(GetUp() * turnForce * (CPad::GetPad(0)->GetSteeringUpDown()/128.0f) * CTimer::GetTimeStep(),
m_vecCentreOfMass + GetForward());
}
}
if(bHoverCheat)
DoHoverSuspensionRatios();
@ -495,7 +543,7 @@ CAutomobile::ProcessControl(void)
m_aSuspensionSpringRatio[1] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[1].surfaceB) == ADHESIVE_SAND ||
m_aSuspensionSpringRatio[2] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[2].surfaceB) == ADHESIVE_SAND ||
m_aSuspensionSpringRatio[3] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[3].surfaceB) == ADHESIVE_SAND){
if(GetModelIndex() != MI_RCBANDIT /*&& GetModelIndex() != MI_SANDKING*/ && GetModelIndex() != MI_BFINJECT){
if(GetModelIndex() != MI_RCBANDIT && GetModelIndex() != MI_SANDKING && GetModelIndex() != MI_BFINJECT){
bStuckInSand = true;
if(CWeather::WetRoads > 0.0f)
ApplyMoveForce(m_vecMoveSpeed * -CTimer::GetTimeStep()*SAND_SLOWDOWN*m_fMass * (1.0f-CWeather::WetRoads));
@ -632,8 +680,7 @@ CAutomobile::ProcessControl(void)
TankControl();
BlowUpCarsInPath();
break;
// LCS: this is gone but i'm keeping it!
case MI_YARDIE:
case MI_VOODOO:
HydraulicControl();
break;
default:
@ -891,6 +938,7 @@ CAutomobile::ProcessControl(void)
if(FindPlayerVehicle() && FindPlayerVehicle() == this)
if(CPad::GetPad(0)->CarGunJustDown())
// TODO(LCS)? re-inline this from CVehicle
ActivateBomb();
if(FindPlayerVehicle() != this && (strongGrip1 || CVehicle::bCheat3)){
@ -924,26 +972,31 @@ CAutomobile::ProcessControl(void)
}
*/
static float magicValue = 4.0f;
float steerRange;
if(fwdSpeed > 0.01f && m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f && m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f && GetStatus() == STATUS_PLAYER){
CColPoint point;
point.surfaceA = SURFACE_WHEELBASE;
point.surfaceB = SURFACE_TARMAC;
float rightSpeed = DotProduct(m_vecMoveSpeed, GetRight());
float adhesion = CSurfaceTable::GetAdhesiveLimit(point);
// i have no idea what's going on here
float magic = traction * adhesion * 16.0f / SQR(fwdSpeed);
magic = Clamp(magic, -1.0f, 1.0f);
magic = Asin(magic);
if(m_fSteerAngle < 0.0f && rightSpeed > 0.05f ||
m_fSteerAngle > 0.0f && rightSpeed < -0.05f ||
bIsHandbrakeOn)
steerRange = 1.0f;
else
steerRange = Min(magic/DEGTORAD(pHandling->fSteeringLock), 1.0f);
if(magicValue > 0.0f){
// looks like a bug with the wheel ids here, why only left wheels?
if(fwdSpeed > 0.01f && (m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f) && GetStatus() == STATUS_PLAYER){
CColPoint point;
point.surfaceA = SURFACE_WHEELBASE;
point.surfaceB = SURFACE_TARMAC;
float rightSpeed = DotProduct(m_vecMoveSpeed, GetRight());
float adhesion = CSurfaceTable::GetAdhesiveLimit(point);
// i have no idea what's going on here
float magic = magicValue * traction * adhesion * 4.0f / SQR(fwdSpeed);
magic = Clamp(magic, -1.0f, 1.0f);
magic = Asin(magic);
if(m_fSteerAngle < 0.0f && rightSpeed > 0.05f ||
m_fSteerAngle > 0.0f && rightSpeed < -0.05f ||
bIsHandbrakeOn)
steerRange = 1.0f;
else
steerRange = Min(magic/DEGTORAD(pHandling->fSteeringLock), 1.0f);
}else
steerRange = 1.0f;
}else
steerRange = 1.0f;
}
m_fSteerAngle *= steerRange;
brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();
@ -964,7 +1017,7 @@ CAutomobile::ProcessControl(void)
float wheelPos = colModel->lines[i].p0.z;
if(m_aSuspensionSpringRatio[i] > 0.0f)
wheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionSpringLength[i];
if(GetModelIndex() == MI_YARDIE && bUsingSpecialColModel) // not original LCS
if(GetModelIndex() == MI_VOODOO && bUsingSpecialColModel)
m_aWheelPosition[i] = wheelPos;
else
m_aWheelPosition[i] += (wheelPos - m_aWheelPosition[i])*0.75f;
@ -978,13 +1031,13 @@ CAutomobile::ProcessControl(void)
}else{
if(UsesSiren()){
if(Pads[0].bHornHistory[Pads[0].iCurrHornHistory]){
if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5] &&
Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+3) % 5])
if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+CPad::HORNHISTORY_SIZE-1) % CPad::HORNHISTORY_SIZE] &&
Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+1) % CPad::HORNHISTORY_SIZE])
m_nCarHornTimer = 1;
else
m_nCarHornTimer = 0;
}else if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5] &&
!Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+1) % 5]){
}else if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+CPad::HORNHISTORY_SIZE-1) % CPad::HORNHISTORY_SIZE] &&
!Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+1) % CPad::HORNHISTORY_SIZE]){
m_nCarHornTimer = 0;
m_bSirenOrAlarm = !m_bSirenOrAlarm;
}else
@ -1009,10 +1062,14 @@ CAutomobile::ProcessControl(void)
if(GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PHYSICS){
if(IsRealHeli()){
bEngineOn = false;
m_aWheelSpeed[1] = Max(m_aWheelSpeed[1]-0.0005f, 0.0f);
if(GetModelIndex() != MI_RCRAIDER && GetModelIndex() != MI_RCGOBLIN)
if(m_aWheelSpeed[1] < 0.154f && m_aWheelSpeed[1] > 0.0044f)
playRotorSound = true;
if(GetStatus() == STATUS_WRECKED)
m_aWheelSpeed[1] = 0.0f;
else{
m_aWheelSpeed[1] = Max(m_aWheelSpeed[1]-0.0005f, 0.0f);
if(GetModelIndex() != MI_RCRAIDER && GetModelIndex() != MI_RCGOBLIN)
if(m_aWheelSpeed[1] < 0.154f && m_aWheelSpeed[1] > 0.0044f)
playRotorSound = true;
}
}
}else if(isPlane && m_vecMoveSpeed.Magnitude() > 0.0f && CTimer::GetTimeStep() > 0.0f){
if(GetModelIndex() == MI_DODO)
@ -1082,7 +1139,7 @@ CAutomobile::ProcessControl(void)
source = GetMatrix()*source + Max(DotProduct(m_vecMoveSpeed, GetForward()), 0.0f)*GetForward()*CTimer::GetTimeStep();
gun.FireProjectile(this, &source, 0.0f);
CStats::RoundsFiredByPlayer++;
// CStats::RoundsFiredByPlayer++;
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
m_nGunFiringTime = CTimer::GetTimeInMilliseconds();
// Hunter gun
@ -1092,7 +1149,7 @@ CAutomobile::ProcessControl(void)
source = GetMatrix()*source + m_vecMoveSpeed*CTimer::GetTimeStep();
gun.FireInstantHit(this, &source);
gun.AddGunshell(this, source, CVector2D(0.0f, 0.1f), 0.025f);
CStats::RoundsFiredByPlayer++;
// CStats::RoundsFiredByPlayer++;
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
m_nGunFiringTime = CTimer::GetTimeInMilliseconds();
}
@ -1104,7 +1161,7 @@ CAutomobile::ProcessControl(void)
source = GetMatrix()*source + m_vecMoveSpeed*CTimer::GetTimeStep();
gun.FireInstantHit(this, &source);
gun.AddGunshell(this, source, CVector2D(0.0f, 0.1f), 0.025f);
CStats::RoundsFiredByPlayer++;
// CStats::RoundsFiredByPlayer++;
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
m_nGunFiringTime = CTimer::GetTimeInMilliseconds();
}
@ -1123,9 +1180,9 @@ CAutomobile::ProcessControl(void)
CMatrix mat;
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BONNET]));
CVector blade = mat.GetRight();
blade = Multiply3x3(blade, GetMatrix());
blade = Multiply3x3(GetMatrix(), blade);
camDist /= Max(Sqrt(distSq), 0.01f);
if(Abs(DotProduct(camDist, blade)) > 0.95f){
if(Abs(DotProduct(camDist, blade)) > HELI_ROTOR_DOTPROD_LIMIT){
DMAudio.PlayOneShot(m_audioEntityId, SOUND_HELI_BLADE, 0.0f);
m_fPropellerRotation = m_aWheelRotation[1];
}
@ -1205,9 +1262,10 @@ CAutomobile::ProcessControl(void)
float suspShake = 0.0f;
float surfShake = 0.0f;
float speedsq = m_vecMoveSpeed.MagnitudeSqr();
float wheelSpin = 0.0f;
for(i = 0; i < 4; i++){
float suspChange = m_aSuspensionSpringRatioPrev[i] - m_aSuspensionSpringRatio[i];
if(suspChange > 0.3f && !drivingInSand && speedsq > 0.04f){
if(suspChange > 0.1f && !drivingInSand && speedsq > SQR(0.2f)){
if(Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST)
DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP_2, suspChange);
else
@ -1232,10 +1290,27 @@ CAutomobile::ProcessControl(void)
// BUG: this only observes one of the wheels
TheCamera.m_bVehicleSuspenHigh = Abs(suspChange) > 0.05f;
if((i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT) && mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) ||
(i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT) && mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))
wheelSpin += WHEELSPIN_TARGET_RATE;
else if(m_aWheelState[i] == WHEEL_STATE_SPINNING)
wheelSpin += WHEELSPIN_INAIR_TARGET_RATE;
m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i];
m_aSuspensionSpringRatio[i] = 1.0f;
}
if(pHandling->Transmission.nDriveType == '4')
wheelSpin /= 4.0f;
else
wheelSpin /= 2.0f;
float spinChange;
if(wheelSpin < m_fWheelSpin)
spinChange = Pow(WHEELSPIN_FALL_RATE, CTimer::GetTimeStep());
else
spinChange = Pow(WHEELSPIN_RISE_RATE, CTimer::GetTimeStep());
m_fWheelSpin = m_fWheelSpin*spinChange + wheelSpin*(1.0f-spinChange);
// Shake pad
if(!drivingInSand && (suspShake > 0.0f || surfShake > 0.0f) && GetStatus() == STATUS_PLAYER){
@ -1322,17 +1397,61 @@ CAutomobile::ProcessControl(void)
CVector(0.0f, 0.0f, 0.0f), nil, 0.7f, col, 0, 0, 0, 3000);
if(CWorld::TestSphereAgainstWorld(GetPosition(), 10.0f, this, true, false, false, false, false, false) ||
GetPosition().z < 6.0f)
GetPosition().z < 0.0f)
if(!bRenderScorched){ // we already know this is true...
CExplosion::AddExplosion(this, nil, EXPLOSION_CAR, GetPosition(), 0);
bRenderScorched = true;
}
}
// The rest was in PreRender
bool onlyFrontWheels = false;
if(IsRealHeli()){
// Looks like LCS actually uses fmodf for the angles but VC has a loop...
// top rotor
m_aWheelRotation[1] += m_aWheelSpeed[1]*CTimer::GetTimeStep();
while(m_aWheelRotation[1] > TWOPI) m_aWheelRotation[1] -= TWOPI;
// rear rotor
m_aWheelRotation[3] += m_aWheelSpeed[1]*CTimer::GetTimeStep();
while(m_aWheelRotation[3] > TWOPI) m_aWheelRotation[3] -= TWOPI;
onlyFrontWheels = true;
}
CVehicleModelInfo *mi = GetModelInfo();
CVector contactPoints[4]; // relative to model
CVector contactSpeeds[4]; // speed at contact points
CVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f));
CVector rearWheelFwd = GetForward();
for(i = 0; i < 4; i++){
if (m_aWheelTimer[i] > 0.0f && (!onlyFrontWheels || i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)) {
contactPoints[i] = m_aWheelColPoints[i].point - GetPosition();
contactSpeeds[i] = GetSpeed(contactPoints[i]);
if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
else
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
m_aWheelRotation[i] += m_aWheelSpeed[i];
}
}
if(GetModelIndex() == MI_DODO){
ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);
ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
}else if(GetModelIndex() == MI_RHINO){
}else if(IsRealHeli()){
}else{
ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);
ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
ProcessSwingingDoor(CAR_DOOR_LR, DOOR_REAR_LEFT);
ProcessSwingingDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT);
ProcessSwingingDoor(CAR_BONNET, DOOR_BONNET);
ProcessSwingingDoor(CAR_BOOT, DOOR_BOOT);
}
}
#pragma optimize("", on)
//--LCS: done
void
CAutomobile::ProcessCarWheelPair(int leftWheel, int rightWheel, float steerAngle, CVector *contactSpeeds, CVector *contactPoints, float traction, float acceleration, float brake, bool bFront)
{
@ -2379,33 +2498,6 @@ CAutomobile::PreRender(void)
CMatrix mat;
CVector pos;
bool onlyFrontWheels = false;
if(IsRealHeli()){
// top rotor
m_aWheelRotation[1] += m_aWheelSpeed[1]*CTimer::GetTimeStep();
if(m_aWheelRotation[1] > TWOPI) m_aWheelRotation[1] -= TWOPI;
// rear rotor
m_aWheelRotation[3] += m_aWheelSpeed[1]*CTimer::GetTimeStep();
if(m_aWheelRotation[3] > TWOPI) m_aWheelRotation[3] -= TWOPI;
onlyFrontWheels = true;
}
CVector contactPoints[4]; // relative to model
CVector contactSpeeds[4]; // speed at contact points
CVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f));
CVector rearWheelFwd = GetForward();
for(i = 0; i < 4; i++){
if (m_aWheelTimer[i] > 0.0f && (!onlyFrontWheels || i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)) {
contactPoints[i] = m_aWheelColPoints[i].point - GetPosition();
contactSpeeds[i] = GetSpeed(contactPoints[i]);
if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
else
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
m_aWheelRotation[i] += m_aWheelSpeed[i];
}
}
RwRGBA hoverParticleCol = { 255, 255, 255, 32 };
// Rear right wheel
@ -2593,9 +2685,6 @@ CAutomobile::PreRender(void)
mat.Translate(pos);
mat.UpdateRW();
}
ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);
ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
}else if(GetModelIndex() == MI_RHINO){
// Front right wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
@ -2731,13 +2820,6 @@ CAutomobile::PreRender(void)
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);
ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
ProcessSwingingDoor(CAR_DOOR_LR, DOOR_REAR_LEFT);
ProcessSwingingDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT);
ProcessSwingingDoor(CAR_BONNET, DOOR_BONNET);
ProcessSwingingDoor(CAR_BOOT, DOOR_BOOT);
}
if((GetModelIndex() == MI_PHEONIX || GetModelIndex() == MI_BFINJECT) &&
@ -2788,6 +2870,7 @@ CAutomobile::Render(void)
{
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 3000;
mi->SetVehicleColour(m_currentColour1, m_currentColour2);
if(IsRealHeli()){
@ -2839,7 +2922,6 @@ CAutomobile::Render(void)
CEntity::Render();
}
//--LCS: done
int32
CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
{
@ -2911,7 +2993,6 @@ static float fMouseCentreRange = 0.35f;
static float fMouseSteerSens = -0.0035f;
static float fMouseCentreMult = 0.975f;
//--LCS: done except TODO
void
CAutomobile::ProcessControlInputs(uint8 pad)
{
@ -3036,12 +3117,12 @@ CAutomobile::ProcessControlInputs(uint8 pad)
// Brake if player isn't in control
// BUG: game always uses pad 0 here
// TODO(LCS): more conditions here
#ifdef FIX_BUGS
if(CPad::GetPad(pad)->ArePlayerControlsDisabled()){
if((CPad::GetPad(pad)->ArePlayerControlsDisabled() || CPad::GetPad(pad)->bApplyBrakes || m_bSuperBrake) &&
#else
if(CPad::GetPad(0)->ArePlayerControlsDisabled()){
if((CPad::GetPad(0)->ArePlayerControlsDisabled() || CPad::GetPad(0)->bApplyBrakes || m_bSuperBrake) &&
#endif
(gMultiplayerSuperBrakeOnPause || m_bSuperBrake)){
m_fBrakePedal = 1.0f;
bIsHandbrakeOn = true;
m_fGasPedal = 0.0f;
@ -3735,7 +3816,7 @@ CAutomobile::DoDriveByShootings(void)
if (!anim || !anim->IsRunning()) {
if (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) {
weapon->FireFromCar(this, lookingLeft, true);
weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;
weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + weapon->GetInfo()->m_nFiringRate;
}
}
}else{
@ -3759,7 +3840,6 @@ CAutomobile::DoDriveByShootings(void)
}
}
//--LCS: done
void
CAutomobile::DoHoverSuspensionRatios(void)
{
@ -3789,10 +3869,10 @@ CAutomobile::DoHoverSuspensionRatios(void)
}else
m_aSuspensionSpringRatio[i] = 0.99999f;
m_aWheelColPoints[i].point.x = (lower.x - upper.x)*m_aSuspensionSpringRatio[i] + upper.x;
m_aWheelColPoints[i].point.y = (lower.y - upper.y)*m_aSuspensionSpringRatio[i] + upper.y;
m_aWheelColPoints[i].point.z = waterZ;
m_aWheelColPoints[i].normal = CVector(0.01f, 0.0f, 1.0f);
m_aWheelColPoints[i].point = CVector((lower.x - upper.x)*m_aSuspensionSpringRatio[i] + upper.x,
(lower.y - upper.y)*m_aSuspensionSpringRatio[i] + upper.y,
waterZ);
m_aWheelColPoints[i].normal = CVector(0.0f, 0.0f, 1.0f);
m_aWheelColPoints[i].surfaceB = SURFACE_WATER;
}
}
@ -4168,6 +4248,7 @@ CAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount)
CVector(0.0f, 0.0f, 0.0f), nil, 0.5f);
n = (int)amount/50 + 1;
n = Min(n, 10);
for(i = 0; i < n; i++)
CParticle::AddParticle(PARTICLE_CAR_DEBRIS, pos,
CVector(CGeneral::GetRandomNumberInRange(-0.25f, 0.25f),
@ -4176,9 +4257,9 @@ CAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount)
nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.08f),
CVehicleModelInfo::mspInfo->ms_vehicleColourTable[m_currentColour1],
CGeneral::GetRandomNumberInRange(-40.0f, 40.0f),
CGeneral::GetRandomNumberInRange(-40, 40),
0,
CGeneral::GetRandomNumberInRange(0.0f, 4.0f));
CGeneral::GetRandomNumberInRange(0, 4));
}
void
@ -4410,7 +4491,9 @@ CAutomobile::OpenDoor(int32 component, eDoors door, float openRatio)
if(Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING)
Damage.SetDoorStatus(door, DOOR_STATUS_OK); // huh?
ShowAllComps();
DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_DOOR_CLOSE_BONNET + door, 0.0f);
// TODO(LCS): this makes no sense at all to me
if(component != CAR_DOOR_LR || IsDoorReady(DOOR_REAR_RIGHT))
DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_DOOR_CLOSE_BONNET + door, 0.0f);
}
axes[Doors[door].m_nAxis] = Doors[door].m_fAngle;
@ -4709,6 +4792,8 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel)
return true;
}
float fBurstForceMult = 0.03f;
void
CAutomobile::BurstTyre(uint8 wheel, bool applyForces)
{
@ -4734,8 +4819,8 @@ CAutomobile::BurstTyre(uint8 wheel, bool applyForces)
}
if(applyForces){
ApplyMoveForce(GetRight() * m_fMass * CGeneral::GetRandomNumberInRange(-0.03f, 0.03f));
ApplyTurnForce(GetRight() * m_fTurnMass * CGeneral::GetRandomNumberInRange(-0.03f, 0.03f), GetForward());
ApplyMoveForce(GetRight() * m_fMass * CGeneral::GetRandomNumberInRange(-fBurstForceMult, fBurstForceMult));
ApplyTurnForce(GetRight() * m_fTurnMass * CGeneral::GetRandomNumberInRange(-fBurstForceMult, fBurstForceMult), GetForward());
}
}
}
@ -4782,7 +4867,7 @@ CAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset)
CVector dist = doorPos - seatPos;
// Removing that makes thiProcessEntityCollisions func. return false for van doors.
// Removing that makes this func. return false for van doors.
doorPos.z += 0.5f;
float length = dist.Magnitude();
CVector pedPos = seatPos + dist*((length+0.6f)/length);
@ -4813,7 +4898,9 @@ CAutomobile::PlayCarHorn(void)
{
uint32 r;
if (IsAlarmOn() || m_nCarHornTimer != 0)
if (IsAlarmOn() ||
this == FindPlayerVehicle() && CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle ||
m_nCarHornTimer != 0)
return;
if (m_nCarHornDelay) {
@ -4856,7 +4943,6 @@ CAutomobile::ResetSuspension(void)
}
}
//--LCS: done
void
CAutomobile::SetupSuspensionLines(void)
{
@ -4949,6 +5035,7 @@ CAutomobile::BlowUpCarsInPath(void)
for(i = 0; i < m_nCollisionRecords; i++)
if(m_aCollisionRecords[i] &&
m_aCollisionRecords[i]->IsVehicle() &&
IsVehiclePointerValid((CVehicle*)m_aCollisionRecords[i]) &&
m_aCollisionRecords[i]->GetModelIndex() != MI_RHINO &&
!m_aCollisionRecords[i]->bRenderScorched){
if(this == FindPlayerVehicle())
@ -5243,6 +5330,7 @@ CAutomobile::Fix(void)
for(component = 0; component < 4; component++)
Damage.SetWheelStatus(component, WHEEL_STATUS_OK);
/*
if(GetModelIndex() == MI_HUNTER){
RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
@ -5252,6 +5340,7 @@ CAutomobile::Fix(void)
RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
}
*/
}
void
@ -5458,13 +5547,14 @@ CAutomobile::SetPanelDamage(int32 component, ePanels panel, bool noFlyingCompone
if(m_aCarNodes[component] == nil)
return;
if(status == PANEL_STATUS_SMASHED1){
DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.0f);
if(panel == VEHPANEL_WINDSCREEN)
DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.0f);
// show damaged part
SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM);
}else if(status == PANEL_STATUS_MISSING){
if(!noFlyingComponents)
SpawnFlyingComponent(component, COMPGROUP_PANEL);
else
else if(panel == VEHPANEL_WINDSCREEN)
CGlass::CarWindscreenShatters(this, false);
// hide both
SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE);

View file

@ -39,6 +39,7 @@ public:
uint8 m_bombType : 3;
#endif
uint8 bTaxiLight : 1;
uint8 bUnknownFlag : 1; // new in LCS
uint8 bFixedColour : 1;
uint8 bBigWheels : 1;
uint8 bWaterTight : 1; // no damage for non-player peds

View file

@ -69,7 +69,6 @@ float TRANSMISSION_AI_CHEAT_MULT = 1.2f;
float TRANSMISSION_SMOOTHER_FRAC = 0.85f;
float TRANSMISSION_FREE_ACCELERATION = 0.1f;
//--LCS: done
float
cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, float *inertiaVar1, float *inertiaVar2, uint8 nDriveWheels, uint8 cheat)
{

View file

@ -53,7 +53,6 @@ bool CVehicle::bDisableRemoteDetonationOnContact;
bool CVehicle::m_bDisplayHandlingInfo;
#endif
float CVehicle::rcHeliHeightLimit = 60.0f;
// unused from SA:
float CVehicle::WHEELSPIN_FALL_RATE = 0.7f;
float CVehicle::WHEELSPIN_RISE_RATE = 0.95f;
float CVehicle::WHEELSPIN_INAIR_TARGET_RATE = 10.0f;
@ -82,12 +81,12 @@ CVehicle::CVehicle(uint8 CreatedBy)
int i;
m_fGasPedal = 0.0f;
m_fBrakePedal = 0.0;
m_vehLCS_264 = 0;
m_fBrakePedal = 0.0f;
m_fWheelSpin = 0.0f;
m_vehLCS_29E = 0;
m_vehLCS_29C = 0;
m_vehLCS_2A3 = -1;
m_vehLCS_348 = false;
m_bSuperBrake = false; // probably for multiplayer
m_nCurrentGear = 1;
m_fChangeGearTime = 0.0f;

View file

@ -256,7 +256,7 @@ public:
int8 m_nPacManPickupsCarried;
uint8 m_nRoadblockType;
uint8 m_bGarageTurnedLightsOff;
int32 m_vehLCS_264;
float m_fWheelSpin;
float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode
float m_fEngineEnergy; // TODO(LCS): better name. it adds up acceleration force, so possibly kinetic energy??
uint8 m_nCurrentGear;
@ -280,8 +280,8 @@ public:
uint8 m_nRadioStation;
uint8 m_bRainAudioCounter;
uint8 m_bRainSamplesCounter;
int8 m_vehLCS_2A3;
int32 m_vehLCS_2A4; // haven't seen this used yet
int8 m_vehLCS_2A3; // enables 2A4
uint8 m_vehLCS_2A4; // some timer
uint32 m_nCarHornTimer;
uint8 m_nCarHornPattern;
uint8 m_bSirenOrAlarm;
@ -292,7 +292,7 @@ public:
CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car
float m_fSteerInput;
eVehicleType m_vehType;
bool m_vehLCS_348;
bool m_bSuperBrake;
static void *operator new(size_t) throw();
static void *operator new(size_t sz, int slot) throw();
@ -429,7 +429,6 @@ public:
static bool m_bDisplayHandlingInfo;
#endif
static float rcHeliHeightLimit;
// unused from SA:
static float WHEELSPIN_FALL_RATE;
static float WHEELSPIN_RISE_RATE;
static float WHEELSPIN_INAIR_TARGET_RATE;