re3-wiiu/src/vehicles/Bike.cpp

783 lines
19 KiB
C++
Raw Normal View History

2020-06-03 08:26:24 +02:00
#include "common.h"
#include "General.h"
#include "Pad.h"
#include "DMAudio.h"
#include "Camera.h"
#include "Darkel.h"
#include "Explosion.h"
#include "World.h"
#include "CarCtrl.h"
#include "Stats.h"
#include "AnimManager.h"
#include "AnimBlendAssociation.h"
#include "Ped.h"
#include "PlayerPed.h"
#include "DamageManager.h"
#include "Vehicle.h"
#include "Automobile.h"
#include "Bike.h"
#define FAKESUSPENSION (99999.992f)
CBike::CBike(int32 id, uint8 CreatedBy)
: CVehicle(CreatedBy)
{
int i;
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
switch(GetModelIndex()){
case MI_ANGEL:
case MI_FREEWAY:
m_bikeAnimType = ASSOCGRP_BIKE_HARLEY;
break;
case MI_PIZZABOY:
case MI_FAGGIO:
m_bikeAnimType = ASSOCGRP_BIKE_VESPA;
break;
case MI_PCJ600:
m_bikeAnimType = ASSOCGRP_BIKE_STANDARD;
break;
case MI_SANCHEZ:
m_bikeAnimType = ASSOCGRP_BIKE_DIRT;
break;
}
m_vehType = VEHICLE_TYPE_BIKE;
m_fFireBlowUpTimer = 0.0f;
m_doingBurnout = 0;
m_bike_flag01 = false;
SetModelIndex(id);
pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
pBikeHandling = mod_HandlingManager.GetBikePointer((eHandlingId)mi->m_handlingId);
pFlyingHandling = mod_HandlingManager.GetFlyingPointer((eHandlingId)mi->m_handlingId);
m_bike_unused1 = 20.0f;
m_bike_unused2 = 0;
mi->ChooseVehicleColour(m_currentColour1, m_currentColour2);
m_fRearForkLength = 0.0f;
m_fFrontForkY = 0.0;
m_fFrontForkZ = 0.0;
m_fFrontForkSlope = Tan(DEGTORAD(mi->m_bikeSteerAngle));
m_fMass = pHandling->fMass;
m_fTurnMass = pHandling->fTurnMass;
m_vecCentreOfMass = pHandling->CentreOfMass;
m_vecCentreOfMass.z = 0.1f;
m_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass;
m_fElasticity = 0.05f;
m_fBuoyancy = pHandling->fBuoyancy;
m_fSteerAngle = 0.0f;
m_fBikeSteerAngle = 0.0f;
m_fLeanLRAngle = 0.0f;
m_fLeanLRAngle2 = 0.0f;
m_fGasPedal = 0.0f;
m_fBrakePedal = 0.0f;
m_fLeanInput = 0.0f;
field_478 = 0;
field_47C = 0;
m_pSetOnFireEntity = nil;
m_pBombRigger = nil;
m_fGasPedalAudio = 0.0f;
m_bike_flag02 = false;
m_bike_flag04 = false;
m_bike_flag08 = false;
m_bike_flag10 = false;
m_bike_flag20 = false;
m_bike_flag40 = false;
m_bike_flag80 = false;
m_fTireTemperature = 0.0f;
someAngle = 0.0f;
field_490 = 0;
for(i = 0; i < 2; i++){
m_aWheelRotation[i] = 0.0f;
m_aWheelSpeed[i] = 0.0f;
m_aWheelState[i] = WHEEL_STATE_NORMAL;
m_aWheelSkidmarkType[i] = SKIDMARK_NORMAL;
m_aWheelSkidmarkBloody[i] = false;
m_aWheelSkidmarkUnk[0] = false;
m_wheelStatus[i] = WHEEL_STATUS_OK;
}
for(i = 0; i < 4; i++){
m_aGroundPhysical[i] = nil;
m_aGroundOffset[i] = CVector(0.0f, 0.0f, 0.0f);
m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i] = 1.0f;
m_aWheelTimer[i] = 0.0f;
}
m_nWheelsOnGround = 0;
m_nDriveWheelsOnGround = 0;
m_nDriveWheelsOnGroundPrev = 0;
m_fHeightAboveRoad = 0.0f;
m_fTraction = 1.0f;
CColModel *colModel = mi->GetColModel();
if(colModel->lines == nil){
colModel->lines = (CColLine*)RwMalloc(4*sizeof(CColLine));
colModel->numLines = 4;
}
// BUG? this would make more sense in the if above
colModel->lines[0].p0.z = FAKESUSPENSION;
SetupSuspensionLines();
AutoPilot.m_nCarMission = MISSION_NONE;
AutoPilot.m_nTempAction = TEMPACT_NONE;
AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
AutoPilot.m_bStayInCurrentLevel = false;
SetStatus(STATUS_SIMPLE);
bUseCollisionRecords = true;
m_nNumPassengers = 0;
bIsVan = false;
bIsBus = false;
bIsBig = false;
bLowVehicle = false;
bPedPhysics = false;
bLeanMatrixClean = false;
m_leanMatrix = GetMatrix();
}
void
CBike::SetModelIndex(uint32 id)
{
CVehicle::SetModelIndex(id);
SetupModelNodes();
}
void
CBike::ProcessControl(void)
{
}
void
CBike::Teleport(CVector pos)
{
CWorld::Remove(this);
SetPosition(pos);
SetOrientation(0.0f, 0.0f, 0.0f);
SetMoveSpeed(0.0f, 0.0f, 0.0f);
SetTurnSpeed(0.0f, 0.0f, 0.0f);
ResetSuspension();
CWorld::Add(this);
}
void
CBike::PreRender(void)
{
}
void
CBike::Render(void)
{
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 3000;
mi->SetVehicleColour(m_currentColour1, m_currentColour2);
CEntity::Render();
}
int32
CBike::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
{
int i;
CColModel *colModel;
if(GetStatus() != STATUS_SIMPLE)
bVehicleColProcessed = true;
colModel = GetColModel();
int numWheelCollisions = 0;
float prevRatios[4] = { 0.0f, 0.0f, 0.0f, 0.0f};
for(i = 0; i < 4; i++)
prevRatios[i] = m_aSuspensionSpringRatio[i];
if(m_bIsVehicleBeingShifted || bSkipLineCol || ent->IsPed() ||
GetModelIndex() == MI_DODO && ent->IsVehicle())
colModel->numLines = 0;
int numCollisions = CCollision::ProcessColModels(GetMatrix(), *colModel,
ent->GetMatrix(), *ent->GetColModel(),
colpoints,
m_aWheelColPoints, m_aSuspensionSpringRatio);
// m_aSuspensionSpringRatio are now set to the point where the tyre touches ground.
// In ProcessControl these will be re-normalized to ignore the tyre radius.
if(colModel->numLines){
for(i = 0; i < 4; i++)
if(m_aSuspensionSpringRatio[i] < 1.0f && m_aSuspensionSpringRatio[i] < prevRatios[i]){
numWheelCollisions++;
// wheel is touching a physical
if(ent->IsVehicle() || ent->IsObject()){
CPhysical *phys = (CPhysical*)ent;
m_aGroundPhysical[i] = phys;
phys->RegisterReference((CEntity**)&m_aGroundPhysical[i]);
m_aGroundOffset[i] = m_aWheelColPoints[i].point - phys->GetPosition();
}
m_nSurfaceTouched = m_aWheelColPoints[i].surfaceB;
if(ent->IsBuilding())
m_pCurGroundEntity = ent;
}
}else
colModel->numLines = 4;
if(numCollisions > 0 || numWheelCollisions > 0){
AddCollisionRecord(ent);
if(!ent->IsBuilding())
((CPhysical*)ent)->AddCollisionRecord(this);
if(numCollisions > 0)
if(ent->IsBuilding() ||
ent->IsObject() && ((CPhysical*)ent)->bInfiniteMass)
bHasHitWall = true;
}
return numCollisions;
}
static int16 nLastControlInput;
static float fMouseCentreRange = 0.35f;
static float fMouseSteerSens = -0.0035f;
static float fMouseCentreMult = 0.975f;
void
CBike::ProcessControlInputs(uint8 pad)
{
float speed = DotProduct(m_vecMoveSpeed, GetForward());
if(CPad::GetPad(pad)->GetExitVehicle())
bIsHandbrakeOn = true;
else
bIsHandbrakeOn = !!CPad::GetPad(pad)->GetHandBrake();
// Steer left/right
#ifdef FIX_BUGS
if(CCamera::m_bUseMouse3rdPerson && !CVehicle::m_bDisableMouseSteering){
if(CPad::GetPad(pad)->GetMouseX() != 0.0f){
m_fSteerInput += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX();
nLastControlInput = 2;
if(Abs(m_fSteerInput) < fMouseCentreRange)
m_fSteerInput *= Pow(fMouseCentreMult, CTimer::GetTimeStep());
}else if(CPad::GetPad(pad)->GetSteeringLeftRight() || nLastControlInput != 2){
// mouse hasn't move, steer with pad like below
m_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)*
0.2f*CTimer::GetTimeStep();
nLastControlInput = 0;
}
}else
#endif
{
m_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)*
0.2f*CTimer::GetTimeStep();
nLastControlInput = 0;
}
m_fSteerInput = clamp(m_fSteerInput, -1.0f, 1.0f);
// Lean forward/backward
float updown = -CPad::GetPad(pad)->GetSteeringUpDown()/128.0f + CPad::GetPad(pad)->GetCarGunUpDown()/128.0f;
m_fLeanInput += (updown - m_fLeanInput)*0.2f*CTimer::GetTimeStep();
m_fLeanInput = clamp(m_fLeanInput, -1.0f, 1.0f);
// Accelerate/Brake
float acceleration = (CPad::GetPad(pad)->GetAccelerate() - CPad::GetPad(pad)->GetBrake())/255.0f;
if(GetModelIndex() == MI_DODO && acceleration < 0.0f)
acceleration *= 0.3f;
if(Abs(speed) < 0.01f){
// standing still, go into direction we want
if(CPad::GetPad(pad)->GetAccelerate() > 150.0f && CPad::GetPad(pad)->GetBrake() > 150.0f){
m_fGasPedal = CPad::GetPad(pad)->GetAccelerate()/255.0f;
m_fBrakePedal = CPad::GetPad(pad)->GetBrake()/255.0f;
m_doingBurnout = 1;
}else{
m_fGasPedal = acceleration;
m_fBrakePedal = 0.0f;
}
}else{
#if 1
// simpler than the code below
if(speed * acceleration < 0.0f){
// if opposite directions, have to brake first
m_fGasPedal = 0.0f;
m_fBrakePedal = Abs(acceleration);
}else{
// accelerating in same direction we were already going
m_fGasPedal = acceleration;
m_fBrakePedal = 0.0f;
}
#else
if(speed < 0.0f){
// moving backwards currently
if(acceleration < 0.0f){
// still go backwards
m_fGasPedal = acceleration;
m_fBrakePedal = 0.0f;
}else{
// want to go forwards, so brake
m_fGasPedal = 0.0f;
m_fBrakePedal = acceleration;
}
}else{
// moving forwards currently
if(acceleration < 0.0f){
// want to go backwards, so brake
m_fGasPedal = 0.0f;
m_fBrakePedal = -acceleration;
}else{
// still go forwards
m_fGasPedal = acceleration;
m_fBrakePedal = 0.0f;
}
}
#endif
}
// Actually turn wheels
static float fValue; // why static?
if(m_fSteerInput < 0.0f)
fValue = -sq(m_fSteerInput);
else
fValue = sq(m_fSteerInput);
m_fSteerAngle = DEGTORAD(pHandling->fSteeringLock) * fValue;
if(bComedyControls){
if(((CTimer::GetTimeInMilliseconds() >> 10) & 0xF) < 12)
m_fGasPedal = 1.0f;
if((((CTimer::GetTimeInMilliseconds() >> 10)+6) & 0xF) < 12)
m_fBrakePedal = 0.0f;
bIsHandbrakeOn = false;
if(CTimer::GetTimeInMilliseconds() & 0x800)
m_fSteerAngle += 0.08f;
else
m_fSteerAngle -= 0.03f;
}
// Brake if player isn't in control
// BUG: game always uses pad 0 here
if(CPad::GetPad(pad)->ArePlayerControlsDisabled()){
m_fBrakePedal = 1.0f;
bIsHandbrakeOn = true;
m_fGasPedal = 0.0f;
FindPlayerPed()->KeepAreaAroundPlayerClear();
// slow down car immediately
speed = m_vecMoveSpeed.Magnitude();
if(speed > 0.28f)
m_vecMoveSpeed *= 0.28f/speed;
}
}
void
CBike::GetComponentWorldPosition(int32 component, CVector &pos)
{
if(m_aBikeNodes[component] == nil){
printf("BikeNode missing: %d %d\n", GetModelIndex(), component);
return;
}
RwMatrix *ltm = RwFrameGetLTM(m_aBikeNodes[component]);
pos = *RwMatrixGetPos(ltm);
}
bool
CBike::IsComponentPresent(int32 component)
{
return m_aBikeNodes[component] != nil;
}
void
CBike::SetComponentRotation(int32 component, CVector rotation)
{
CMatrix mat(RwFrameGetMatrix(m_aBikeNodes[component]));
CVector pos = mat.GetPosition();
// BUG: all these set the whole matrix
mat.SetRotateX(DEGTORAD(rotation.x));
mat.SetRotateY(DEGTORAD(rotation.y));
mat.SetRotateZ(DEGTORAD(rotation.z));
mat.Translate(pos);
mat.UpdateRW();
}
bool
CBike::IsDoorReady(eDoors door)
{
return true;
}
bool
CBike::IsDoorFullyOpen(eDoors door)
{
return false;
}
bool
CBike::IsDoorClosed(eDoors door)
{
return false;
}
bool
CBike::IsDoorMissing(eDoors door)
{
return true;
}
void
CBike::RemoveRefsToVehicle(CEntity *ent)
{
int i;
for(i = 0; i < 4; i++)
if(m_aGroundPhysical[i] == ent)
m_aGroundPhysical[i] = nil;
}
void
CBike::BlowUpCar(CEntity *culprit)
{
if(!bCanBeDamaged)
return;
// explosion pushes vehicle up
m_vecMoveSpeed.z += 0.13f;
SetStatus(STATUS_WRECKED);
bRenderScorched = true;
m_fHealth = 0.0f;
m_nBombTimer = 0;
TheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z);
KillPedsInVehicle();
bEngineOn = false;
bLightsOn = false;
ChangeLawEnforcerState(false);
CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0);
CDarkel::RegisterCarBlownUpByPlayer(this);
}
bool
CBike::SetUpWheelColModel(CColModel *colModel)
{
// TODO, but unused
return true;
}
void
CBike::BurstTyre(uint8 wheel, bool applyForces)
{
if(bTyresDontBurst)
return;
switch(wheel){
case CAR_PIECE_WHEEL_LF: wheel = BIKEWHEEL_FRONT; break;
case CAR_PIECE_WHEEL_LR: wheel = BIKEWHEEL_REAR; break;
default: assert(0 && "invalid wheel");
}
if(m_wheelStatus[wheel] == WHEEL_STATUS_OK){
m_wheelStatus[wheel] = WHEEL_STATUS_BURST;
#ifdef FIX_BUGS
CStats::TyresPopped++;
#endif
// TODO(MIAMI)
// DMAudio.PlayOneShot(m_audioEntityId, SOUND_15, 0.0f);
if(GetStatus() == STATUS_SIMPLE){
SetStatus(STATUS_PHYSICS);
CCarCtrl::SwitchVehicleToRealPhysics(this);
}
if(applyForces){
ApplyMoveForce(GetRight() * m_fMass * CGeneral::GetRandomNumberInRange(-0.02f, 0.02f));
ApplyTurnForce(GetRight() * m_fTurnMass * CGeneral::GetRandomNumberInRange(-0.02f, 0.02f), GetForward());
}
// TODO: knock off driver
}
}
bool
CBike::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset)
{
CColPoint colpoint;
CEntity *ent;
colpoint.point = CVector(0.0f, 0.0f, 0.0f);
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
CVector seatPos = mi->GetFrontSeatPosn();
if(component == CAR_DOOR_RR || component == CAR_DOOR_LR)
seatPos = mi->m_positions[CAR_POS_BACKSEAT];
if(component == CAR_DOOR_LF || component == CAR_DOOR_LR)
seatPos.x = -seatPos.x;
seatPos = GetMatrix() * seatPos;
CVector doorPos = CPed::GetPositionToOpenCarDoor(this, component);
if(doorOffset){
CVector off = *doorOffset;
if(component == CAR_DOOR_RF || component == CAR_DOOR_RR)
off.x = -off.x;
doorPos += Multiply3x3(GetMatrix(), off);
}
if(GetUp().z < 0.0f){
seatPos.z += 0.5f;
doorPos.z += 0.5f;
}
CVector dist = doorPos - seatPos;
// Removing that makes thiProcessEntityCollisions func. return false for van doors.
doorPos.z += 0.5f;
float length = dist.Magnitude();
CVector pedPos = seatPos + dist*((length+0.6f)/length);
if(!CWorld::GetIsLineOfSightClear(seatPos, pedPos, true, false, false, true, false, false))
return false;
if(CWorld::TestSphereAgainstWorld(doorPos, 0.6f, this, true, true, false, true, false, false))
return false;
if(CWorld::ProcessVerticalLine(doorPos, 1000.0f, colpoint, ent, true, false, false, true, false, false, nil))
if(colpoint.point.z > doorPos.z && colpoint.point.z < doorPos.z + 0.6f)
return false;
float upperZ = colpoint.point.z;
if(!CWorld::ProcessVerticalLine(doorPos, -1000.0f, colpoint, ent, true, false, false, true, false, false, nil))
return false;
if(upperZ != 0.0f && upperZ < colpoint.point.z)
return false;
return true;
}
float
CBike::GetHeightAboveRoad(void)
{
return m_fHeightAboveRoad;
}
void
CBike::PlayCarHorn(void)
{
int r;
if (IsAlarmOn() || m_nCarHornTimer != 0)
return;
if (m_nCarHornDelay) {
m_nCarHornDelay--;
return;
}
m_nCarHornDelay = (CGeneral::GetRandomNumber() & 0x7F) + 150;
r = m_nCarHornDelay & 7;
if(r < 2){
m_nCarHornTimer = 45;
}else if(r < 4){
if(pDriver)
pDriver->Say(SOUND_PED_CAR_COLLISION);
m_nCarHornTimer = 45;
}else{
if(pDriver)
pDriver->Say(SOUND_PED_CAR_COLLISION);
}
}
void
CBike::PlayHornIfNecessary(void)
{
if(AutoPilot.m_bSlowedDownBecauseOfPeds ||
AutoPilot.m_bSlowedDownBecauseOfCars)
PlayCarHorn();
}
void
CBike::ResetSuspension(void)
{
int i;
for(i = 0; i < 2; i++){
m_aWheelRotation[i] = 0.0f;
m_aWheelState[i] = WHEEL_STATE_NORMAL;
}
for(i = 0; i < 4; i++){
m_aSuspensionSpringRatio[i] = 1.0f;
m_aWheelTimer[i] = 0.0f;
}
}
// TODO: maybe put this somewhere else
inline void
GetRelativeMatrix(RwMatrix *mat, RwFrame *frm, RwFrame *end)
{
*mat = *RwFrameGetMatrix(frm);
frm = RwFrameGetParent(frm);
while(frm){
RwMatrixTransform(mat, RwFrameGetMatrix(frm), rwCOMBINEPOSTCONCAT);
frm = RwFrameGetParent(frm);
if(frm == end)
frm = nil;
}
}
void
CBike::SetupSuspensionLines(void)
{
int i;
CVector posn;
float suspOffset = 0.0f;
RwFrame *node = nil;
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
CColModel *colModel = mi->GetColModel();
RwMatrix *mat = RwMatrixCreate();
bool initialized = colModel->lines[0].p0.z != FAKESUSPENSION;
for(i = 0; i < 4; i++){
if(initialized){
posn = colModel->lines[i].p0;
if(i < 2)
posn.z = m_aWheelBasePosition[0];
else
posn.z = m_aWheelBasePosition[1];
}else{
switch(i){
case BIKESUSP_FRONT_1:
node = m_aBikeNodes[BIKE_WHEEL_FRONT];
suspOffset = 0.25f*mi->m_wheelScale;
break;
case BIKESUSP_FRONT_2:
node = m_aBikeNodes[BIKE_WHEEL_FRONT];
suspOffset = -0.25f*mi->m_wheelScale;
break;
case BIKESUSP_REAR_1:
node = m_aBikeNodes[BIKE_WHEEL_REAR];
suspOffset = 0.25f*mi->m_wheelScale;
break;
case BIKESUSP_REAR_2:
node = m_aBikeNodes[BIKE_WHEEL_REAR];
suspOffset = -0.25f*mi->m_wheelScale;
break;
}
GetRelativeMatrix(mat, node, node);
posn = *RwMatrixGetPos(mat);
if(i == BIKESUSP_FRONT_1)
m_aWheelBasePosition[BIKEWHEEL_FRONT] = posn.z;
else if(i == BIKESUSP_REAR_1){
m_aWheelBasePosition[BIKEWHEEL_REAR] = posn.z;
GetRelativeMatrix(mat, node, m_aBikeNodes[BIKE_FORKS_REAR]);
float dz = posn.z - RwMatrixGetPos(mat)->z;
float dy = posn.y - RwMatrixGetPos(mat)->y;
m_fRearForkLength = Sqrt(SQR(dy) + SQR(dz));
}
posn.y += suspOffset;
}
// uppermost wheel position
posn.z += pHandling->fSuspensionUpperLimit;
colModel->lines[i].p0 = posn;
// lowermost wheel position
posn.z += pHandling->fSuspensionLowerLimit - pHandling->fSuspensionUpperLimit;
// lowest point on tyre
posn.z -= mi->m_wheelScale*0.5f;
colModel->lines[i].p1 = posn;
// this is length of the spring at rest
m_aSuspensionSpringLength[i] = pHandling->fSuspensionUpperLimit - pHandling->fSuspensionLowerLimit;
m_aSuspensionLineLength[i] = colModel->lines[i].p0.z - colModel->lines[i].p1.z;
}
if(!initialized){
GetRelativeMatrix(mat, m_aBikeNodes[BIKE_FORKS_REAR], m_aBikeNodes[BIKE_FORKS_REAR]);
m_fFrontForkY = RwMatrixGetPos(mat)->y;
m_fFrontForkZ = RwMatrixGetPos(mat)->z;
}
// Compress spring somewhat to get normal height on road
m_fHeightAboveRoad = m_aSuspensionSpringLength[0]*(1.0f - 1.0f/(4.0f*pHandling->fSuspensionForceLevel))
- colModel->lines[0].p0.z + mi->m_wheelScale*0.5f;
for(i = 0; i < 2; i++)
m_aWheelPosition[i] = mi->m_wheelScale*0.5f - m_fHeightAboveRoad;
// adjust col model to include suspension lines
if(colModel->boundingBox.min.z > colModel->lines[0].p1.z)
colModel->boundingBox.min.z = colModel->lines[0].p1.z;
float radius = Max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude());
if(colModel->boundingSphere.radius < radius)
colModel->boundingSphere.radius = radius;
#ifdef FIX_BUGS
RwMatrixDestroy(mat);
#endif
}
void
CBike::CalculateLeanMatrix(void)
{
if(bLeanMatrixClean)
return;
CMatrix mat;
mat.SetRotateX(-0.05f*Abs(m_fLeanLRAngle));
mat.RotateY(m_fLeanLRAngle);
m_leanMatrix = GetMatrix();
m_leanMatrix = m_leanMatrix * mat;
// place wheel back on ground
m_leanMatrix.GetPosition() += GetUp()*(1.0f-Cos(m_fLeanLRAngle))*GetColModel()->boundingBox.min.z;
bLeanMatrixClean = true;
}
void
CBike::GetCorrectedWorldDoorPosition(CVector &pos, CVector p1, CVector p2)
{
CVector &fwd = GetForward();
CVector rightWorld = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));
CVector upWorld = CrossProduct(rightWorld, fwd);
CColModel *colModel = GetColModel();
float onSide = DotProduct(GetUp(), rightWorld);
float diff = Max(colModel->boundingBox.max.z-colModel->boundingBox.max.x, 0.0f);
pos = CVector(0.0f, 0.0f, 0.0f);
float y = p2.y - p1.y;
float x = onSide*diff + p2.x + p1.x;
float z = p2.z - p1.z;
pos = x*rightWorld + y*fwd + z*upWorld + GetPosition();
}
void
CBike::Fix(void)
{
bIsDamaged = false;
m_bike_flag40 = false;
m_wheelStatus[0] = WHEEL_STATUS_OK;
m_wheelStatus[1] = WHEEL_STATUS_OK;
}
void
CBike::SetupModelNodes(void)
{
int i;
for(i = 0; i < BIKE_NUM_NODES; i++)
m_aBikeNodes[i] = nil;
CClumpModelInfo::FillFrameArray(GetClump(), m_aBikeNodes);
}
void
CBike::ReduceHornCounter(void)
{
if(m_nCarHornTimer != 0)
m_nCarHornTimer--;
}