The-Simpsons-Hit-and-Run/game/code/worldsim/vehiclecentral.cpp

2279 lines
70 KiB
C++

//=============================================================================
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
//
// File: vehiclecentral.cpp
//
// Description: bleek
//
// History: May 1, 2002 - created, gmayer
//
//=============================================================================
//========================================
// System Includes
//========================================
#include <raddebug.hpp>
#include <stdlib.h> // for atof
//========================================
// Project Includes
//========================================
#include <worldsim/worldphysicsmanager.h>
#include <worldsim/vehiclecentral.h>
#include <worldsim/redbrick/vehiclecontroller/vehiclecontroller.h>
#include <worldsim/character/character.h>
#include <worldsim/character/charactermanager.h>
#include <worldsim/avatarmanager.h>
#include <ai/actionbuttonhandler.h>
#include <ai/actionbuttonmanager.h>
#include <memory/srrmemory.h>
#include <mission/gameplaymanager.h>
#include <meta/eventlocator.h>
#include <meta/spheretriggervolume.h>
#include <meta/triggervolumetracker.h>
#include <debug/debuginfo.h>
#include <mission/gameplaymanager.h>
#include <mission/missionscriptloader.h>
#include <render/RenderManager/RenderManager.h>
#include <render/Culling/WorldScene.h>
#include <gameflow/gameflow.h>
#include <console/console.h>
#include <cheats/cheatinputsystem.h>
#include <p3d/billboardobject.hpp>
//******************************************************************************
//
// Global Data, Local Data, Local Classes
//
//******************************************************************************
VehicleCentral* VehicleCentral::spInstance = 0;
AiVehicleController* VehicleCentral::spGenericAI = NULL;
//
// Dusit here:
// First, keep MAX_HUSKS defined in the .cpp so we can tweak without
// recompiling the whole game...
// Now, how many husks can we possibly need in the WORST case??
// traffic 5
// parked cars 5
// harass 5
// player 1
// mission ai 4
// main ai 1
// free (moment) cars 1-2 (?)
// This is too many (23). At 17KB per Vehicle instance + 35KB Husk model,
// it would total between 420 and 500 KB... Unacceptable.
// So we have forced the other systems to deal safely with not having
// husks available when they need it (RequestHusk may return NULL)
//
const int MAX_HUSKS = 5;
//=============================================================================
// VehicleCentral::VehicleCentral
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: VehicleCentral
//
//=============================================================================
VehicleCentral::VehicleCentral() :
mCurrentVehicleUnderContructionHead( 0 ),
mCurrentVehicleUnderConstructionTail( 0 ),
mbVehicleTriggersActive(true),
mSuppressedDriverCount(0)
{
spGenericAI = new AiVehicleController( NULL );
spGenericAI->AddRef();
int i;
for(i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
mActiveVehicleList[i] = 0;
//mActiveVehicleControllerList[ i ] = NULL;
mActiveVehicleControllerList[ i ] = spGenericAI;
mActiveVehicleControllerList[ i ]->AddRef();
mVehicleUnderConstruction[ i ] = NULL;
//mDoorTriggerList[ i ] = 0;
}
mNumActiveVehicles = 0;
// perhaps this would be a good place to setup the console functions for the vehicle
SetupConsoleFunctionsForVehicleTuning();
for( i=0; i<NUM_HEADLIGHT_BBQGS; i++ )
{
mHeadLights[i] = NULL;
}
}
//==============
// console hooks
//==============
static void ConsoleHookSetGasScale(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetGasScale(value);
}
static void ConsoleHookSetSlipGasScale(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetSlipGasScale(value);
}
static void ConsoleHookSetHighSpeedGasScale(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetHighSpeedGasScale(value);
}
static void ConsoleHookSetGasScaleSpeedThreshold(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetGasScaleSpeedThreshold(value);
}
static void ConsoleHookSetBrakeScale(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetBrakeScale(value);
}
static void ConsoleHookSetTopSpeedKmh(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetTopSpeedKmh(value);
}
static void ConsoleHookSetMass(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetMass(value);
}
static void ConsoleHookSetMaxWheelTurnAngle(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetMaxWheelTurnAngle(value);
}
static void ConsoleHookSetHighSpeedSteeringDrop(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetHighSpeedSteeringDrop(value);
}
static void ConsoleHookSetTireLateralStaticGrip(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetTireLateralStaticGrip(value);
}
static void ConsoleHookSetTireLateralResistanceNormal(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetTireLateralResistanceNormal(value);
}
static void ConsoleHookSetTireLateralResistanceSlip(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetTireLateralResistanceSlip(value);
}
static void ConsoleHookSetEBrakeEffect(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetEBrakeEffect(value);
}
static void ConsoleHookSetCMOffsetX(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetCMOffsetX(value);
}
static void ConsoleHookSetCMOffsetY(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetCMOffsetY(value);
}
static void ConsoleHookSetCMOffsetZ(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetCMOffsetZ(value);
}
static void ConsoleHookSetSuspensionLimit(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetSuspensionLimit(value);
}
static void ConsoleHookSetSpringK(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetSuspensionSpringK(value);
}
static void ConsoleHookSetDamperC(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetSuspensionDamperC(value);
}
static void ConsoleHookSetHitPoints(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetHitPoints(value);
}
static void ConsoleHookSetSuspensionYOffset(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetSuspensionYOffset(value);
}
static void ConsoleHookSetBurnoutRange(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetBurnoutRange(value);
}
static void ConsoleHookSetMaxSpeedBurstTime(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetMaxSpeedBurstTime(value);
}
static void ConsoleHookSetDonutTorque(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetDonutTorque(value);
}
static void ConsoleHookSetSlipSteeringNoEBrake(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetTireLateralResistanceSlipWithoutEBrake(value);
}
static void ConsoleHookSetSlipEffectNoEBrake(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetSlipEffectWithoutEBrake(value);
}
static void ConsoleHookSetWeebleOffset(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetWeebleOffset(value);
}
static void ConsoleHookSetWheelieRange(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetWheelieRange(value);
}
static void ConsoleHookSetWheelieOffsetY(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetWheelieYOffset(value);
}
static void ConsoleHookSetWheelieOffsetZ(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetWheelieZOffset(value);
}
static void ConsoleHookSetShininess( int argc, char** argv )
{
if( argc != 2 )
{
return;
}
float shininess = static_cast<float>( atof( argv[ 1 ] ) );
unsigned char ref = rmt::Clamp( int( 0xff * shininess ), 0, 0xff );
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetShininess( ref );
}
static void ConsoleHookSetShadowAdjustments( int argc, char** argv )
{
if( argc != 9 )
{
return;
}
float Adjustments[ 4 ][ 2 ];
for( int i = 0; i < 4; ++i )
{
Adjustments[ i ][ 0 ] = static_cast<float>( atof( argv[ 1 + ( i * 2 ) ] ) );
Adjustments[ i ][ 1 ] = static_cast<float>( atof( argv[ 2 + ( i * 2 ) ] ) );
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetShadowAdjustments( Adjustments );
}
static void ConsoleHookSetDriverName(int argc, char** argv)
{
if(argc != 2)
{
return;
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetDriverName(argv[1]);
}
static void ConsoleHookSetHasDoors(int argc, char** argv)
{
if(argc != 2)
{
return;
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->mHasDoors = (atoi(argv[1]) != 0);
}
static void ConsoleHookSetCharactersVisible(int argc, char** argv)
{
if(argc != 2)
{
return;
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->mVisibleCharacters = (atoi(argv[1]) != 0);
}
static void ConsoleHookSetIrisTransition(int argc, char** argv)
{
if(argc != 2)
{
return;
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->mIrisTransition = (atoi(argv[1]) != 0);
}
static void ConsoleHookSetAllowSlide(int argc, char** argv)
{
if(argc != 2)
{
return;
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->mAllowSlide = (atoi(argv[1]) != 0);
}
static void ConsoleHookSetHighRoof(int argc, char** argv)
{
if(argc != 2)
{
return;
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->mHighRoof = (atoi(argv[1]) != 0);
}
static void ConsoleHookSetCharacterScale(int argc, char** argv)
{
if(argc != 2)
{
return;
}
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->mCharacterScale = static_cast< float >( atof(argv[1]) );
}
//Chuck: added this for Gambling Races.
static void ConsoleHookSetGamblingOdds(int argc, char** argv)
{
if(argc != 2)
{
return;
}
float value = static_cast<float>(atof(argv[1]));
GetVehicleCentral()->GetCurrentVehicleUnderConstruction()->SetGamblingOdds(value);
}
static void ConsoleHookSuppressDriver(int argc, char** argv)
{
GetVehicleCentral()->AddSuppressedDriver(argv[1]);
}
//=============================================================================
// VehicleCentral::SetupConsoleFunctionsForVehicleTuning
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::SetupConsoleFunctionsForVehicleTuning()
{
GetConsole()->AddFunction("SetMass", ConsoleHookSetMass, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetGasScale", ConsoleHookSetGasScale, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetHighSpeedGasScale", ConsoleHookSetHighSpeedGasScale, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetGasScaleSpeedThreshold", ConsoleHookSetGasScaleSpeedThreshold, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetSlipGasScale", ConsoleHookSetSlipGasScale, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetBrakeScale", ConsoleHookSetBrakeScale, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetTopSpeedKmh", ConsoleHookSetTopSpeedKmh, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetMaxWheelTurnAngle", ConsoleHookSetMaxWheelTurnAngle, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetHighSpeedSteeringDrop", ConsoleHookSetHighSpeedSteeringDrop, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetTireGrip", ConsoleHookSetTireLateralStaticGrip, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetNormalSteering", ConsoleHookSetTireLateralResistanceNormal, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetSlipSteering", ConsoleHookSetTireLateralResistanceSlip, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetEBrakeEffect", ConsoleHookSetEBrakeEffect, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetCMOffsetX", ConsoleHookSetCMOffsetX, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetCMOffsetY", ConsoleHookSetCMOffsetY, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetCMOffsetZ", ConsoleHookSetCMOffsetZ, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetSuspensionLimit", ConsoleHookSetSuspensionLimit, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetSpringK", ConsoleHookSetSpringK, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetDamperC", ConsoleHookSetDamperC, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetSuspensionYOffset", ConsoleHookSetSuspensionYOffset, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetHitPoints", ConsoleHookSetHitPoints, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetBurnoutRange", ConsoleHookSetBurnoutRange, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetMaxSpeedBurstTime", ConsoleHookSetMaxSpeedBurstTime, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetDonutTorque", ConsoleHookSetDonutTorque, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetSlipSteeringNoEBrake", ConsoleHookSetSlipSteeringNoEBrake, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetSlipEffectNoEBrake", ConsoleHookSetSlipEffectNoEBrake, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetWeebleOffset", ConsoleHookSetWeebleOffset, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetWheelieRange", ConsoleHookSetWheelieRange, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetWheelieOffsetY", ConsoleHookSetWheelieOffsetY, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetWheelieOffsetZ", ConsoleHookSetWheelieOffsetZ, "help your goddamn self", 1, 1);
GetConsole()->AddFunction( "SetShadowAdjustments", ConsoleHookSetShadowAdjustments, "Move the shadow points around", 8, 8 );
GetConsole()->AddFunction( "SetShininess", ConsoleHookSetShininess, "Set the environmental reflection 0 to 1", 1, 1 );
GetConsole()->AddFunction("SetDriver", ConsoleHookSetDriverName, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetGamblingOdds",ConsoleHookSetGamblingOdds,"Set Gambling Odds",1,1);
GetConsole()->AddFunction("SetHasDoors", ConsoleHookSetHasDoors, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetCharactersVisible", ConsoleHookSetCharactersVisible, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetIrisTransition", ConsoleHookSetIrisTransition, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetAllowSeatSlide", ConsoleHookSetAllowSlide, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetHighRoof", ConsoleHookSetHighRoof, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SetCharacterScale", ConsoleHookSetCharacterScale, "help your goddamn self", 1, 1);
GetConsole()->AddFunction("SuppressDriver", ConsoleHookSuppressDriver, "help your goddamn self", 1, 1);
}
//=============================================================================
// VehicleCentral::~VehicleCentral
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: VehicleCentral
//
//=============================================================================
VehicleCentral::~VehicleCentral()
{
ClearSuppressedDrivers();
int i;
for(i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
if(mActiveVehicleList[i])
{
// TODO - will the mission manager delete these instead??
//
// for now, only delete the ones that were left in there...
delete mActiveVehicleList[i];
}
if ( this->mActiveVehicleControllerList[ i ] )
{
mActiveVehicleControllerList[ i ]->Release();
mActiveVehicleControllerList[ i ] = NULL;
}
/*
if ( mDoorTriggerList[ i ] )
{
mDoorTriggerList[ i ]->Release( );
mDoorTriggerList[ i ] = 0;
}
*/
}
// create a static vehicle AI and put it in limbo...
if( spGenericAI )
{
spGenericAI->ReleaseVerified();
}
for( i=0; i<NUM_HEADLIGHT_BBQGS; i++ )
{
if( mHeadLights[i] )
{
mHeadLights[i]->Release();
mHeadLights[i] = NULL;
}
}
}
//=============================================================================
// VehicleCentral::GetInstance
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: VehicleCentral
//
//=============================================================================
VehicleCentral* VehicleCentral::GetInstance()
{
rAssert(spInstance);
return spInstance;
}
//=============================================================================
// VehicleCentral::CreateInstance
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: VehicleCentral
//
//=============================================================================
VehicleCentral* VehicleCentral::CreateInstance()
{
rAssert(spInstance == 0);
spInstance = new(GMA_PERSISTENT) VehicleCentral;
rAssert(spInstance);
return spInstance;
}
//=============================================================================
// VehicleCentral::DestroyInstance
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::DestroyInstance()
{
rAssert(spInstance);
delete(GMA_PERSISTENT, spInstance);
spInstance = NULL;
}
//=============================================================================
// VehicleCentral::InitHuskPool
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::InitHuskPool()
{
}
//=============================================================================
// VehicleCentral::FreeHuskPool
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::FreeHuskPool()
{
}
//=============================================================================
// VehicleCentral::PreLoad
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::PreLoad()
{
// bunch of actual loading moved to frontend startup to reduce load times - nbrooke 3/7/2003
this->mHuskPool.Init(MAX_HUSKS);
rAssert( mHeadLights[0] == NULL && mHeadLights[1] == NULL && mHeadLights[2] == NULL );
// also might as well load the vehicle commons here..
p3d::inventory->PushSection();
p3d::inventory->SelectSection( "Global" );
bool oldCurrSectionOnly = p3d::inventory->GetCurrentSectionOnly();
p3d::inventory->SetCurrentSectionOnly( true );
tRefCounted::Assign( mHeadLights[0], p3d::find<tBillboardQuadGroup>(tEntity::MakeUID("headlightShape8")) );
tRefCounted::Assign( mHeadLights[1], p3d::find<tBillboardQuadGroup>(tEntity::MakeUID("headlight2Shape")) );
tRefCounted::Assign( mHeadLights[2], p3d::find<tBillboardQuadGroup>(tEntity::MakeUID("glowGroupShape2")) );
p3d::inventory->SetCurrentSectionOnly( oldCurrSectionOnly );
p3d::inventory->PopSection();
// grab the colours from the bbqgs
int count = 0;
for( int i=0; i<NUM_HEADLIGHT_BBQGS; i++ )
{
rAssert( mHeadLights[i] );
for( int j=0; j<mHeadLights[i]->GetNumQuads(); j++ )
{
tBillboardQuad* quad = mHeadLights[i]->GetQuad( j );
rAssert( quad );
mOriginalHeadLightColours[count] = quad->GetColour();
count++;
}
}
rAssert( mHeadLights[0] && mHeadLights[1] && mHeadLights[2] );
}
//=============================================================================
// VehicleCentral::Unload
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::Unload()
{
// empty out husk manager here also
this->mHuskPool.Empty();
ClearSuppressedDrivers();
int count = 0;
// restore prev states and release all preloaded headlights bbqgs
for( int i=0; i<NUM_HEADLIGHT_BBQGS; i++ )
{
rAssert( mHeadLights[i] );
for( int j=0; j<mHeadLights[i]->GetNumQuads(); j++ )
{
tBillboardQuad* quad = mHeadLights[i]->GetQuad( j );
rAssert( quad );
quad->SetColour( mOriginalHeadLightColours[count] );
count++;
}
// ProcessShaders screwed us by causing us to lose the additive blend
// We set it back.
mHeadLights[i]->GetShader()->SetInt( PDDI_SP_BLENDMODE, PDDI_BLEND_ADD );
mHeadLights[i]->Release();
mHeadLights[i] = NULL;
}
rAssert(mNumActiveVehicles == 0);
}
//=============================================================================
// VehicleCentral::InitVehicle
//=============================================================================
// Description: Comment
//
// Parameters: ( const char* name )
//
// Return: void
//
//=============================================================================
Vehicle* VehicleCentral::InitVehicle( const char* name, bool addToActiveVehicleList, char* confile, VehicleType vt, DriverInit driver, bool playercar, bool startoutofcar)
{
HeapMgr()->PushHeap( GetGameplayManager()->GetCurrentMissionHeap() );
MEMTRACK_PUSH_GROUP( "VehicleCentral" );
//#ifdef RAD_GAMECUBE
// Vehicle* vehicle = new( GMA_GC_VMM ) Vehicle;
//#else
Vehicle* vehicle = new(GetGameplayManager()->GetCurrentMissionHeap()) Vehicle;
//#endif
//if this car is owned by the player then set the flag.
if(playercar ==true)
{
vehicle->mbPlayerCar=true;
}
// note: moved the car open-door locator to the vehicle init
bool ok = vehicle->Init( name, GetWorldPhysicsManager()->mSimEnvironment, VL_PHYSICS, vt, startoutofcar);
rAssert(ok);
// so the script hooks can get at it
rAssert( mVehicleUnderConstruction[mCurrentVehicleUnderConstructionTail] == NULL );
mVehicleUnderConstruction[mCurrentVehicleUnderConstructionTail] = vehicle;
mCurrentVehicleUnderConstructionTail = (mCurrentVehicleUnderConstructionTail + 1) % MAX_ACTIVE_VEHICLES;
//If this happens, we're in big shit. We'll need to up the number of active vehicles or look closer at the loading.
rAssert( mCurrentVehicleUnderContructionHead != mCurrentVehicleUnderConstructionTail );
// see TODO in comment blocks above
// DL: now loads the car based on name
char scriptname[64];
strcpy( scriptname, "scripts/cars/" );
if(confile != NULL && confile[0] != '\0')
{
strcat( scriptname, confile );
}
else
{
strcat( scriptname, name );
strcat( scriptname, ".con" );
}
vehicle->mDriverInit = driver;
GetMissionScriptLoader()->LoadScriptAsync( scriptname, this );
//vehicle->CalculateValuesBasedOnDesignerParams();
if(addToActiveVehicleList)
{
// return slot ignored here...
int dummy = AddVehicleToActiveList(vehicle);
}
MEMTRACK_POP_GROUP( "VehicleCentral" );
HeapMgr()->PopHeap( GetGameplayManager()->GetCurrentMissionHeap() );
return vehicle;
}
//=============================================================================
// VehicleCentral::AddVehicleToActiveList
//=============================================================================
// Description: Comment
//
// returns index if successful, otherwise -1
//
// Parameters: VehicleCentral::AddVehicleToActiveList
//
// Return: int
//
//=============================================================================
int VehicleCentral::AddVehicleToActiveList(Vehicle* vehicle)
{
//==============================================================================
//
// let's be clear here:
//
// an 'active' vehicle is one that will be added to the dsg
// it will also request a collision area index and put itself in there,
// but it won't do it's own query to fill that area unless it's under VL_PHYSICS
//
//==============================================================================
// find this vehicle a slot
int slot = -1;
int i;
for(i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
// debug test
if(mActiveVehicleList[i])
{
if(mActiveVehicleList[i] == vehicle)
{
// this is already in our list!!!!
//rAssertMsg( false, "This vehicle is already in the active list\n");
return i;
//chuck: draw the driver
if (vehicle->GetDriver() !=NULL)
{
vehicle->GetDriver()->AddToWorldScene();
}
}
}
}
for(i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
if(mActiveVehicleList[i] == 0)
{
// got it.
slot = i;
break;
}
}
if(slot == -1)
{
// couldn't find room for it.
//?
rAssertMsg(0,"Trying to add too many active vehicles!");
return -1;
}
//----------
// add it in
//----------
mActiveVehicleList[slot] = vehicle;
if (vehicle->GetDriver() !=NULL)
{
vehicle->GetDriver()->AddToWorldScene();
}
// this is perhaps totally redundant right now
mNumActiveVehicles++;
if(mNumActiveVehicles > MAX_ACTIVE_VEHICLES)
{
rAssertMsg(0,"Too many active vehicles!");
return -1;
}
//--------------------
// trigger volume shit
//--------------------
if( vehicle->mVehicleType == VT_AI &&
::GetGameFlow()->GetCurrentContext() != CONTEXT_SUPERSPRINT &&
!GetGameplayManager()->mIsDemo )
{
GetTriggerVolumeTracker()->RegisterAI( vehicle );
}
int id = vehicle->mpEventLocator->GetData();
ActionButton::GetInCar* pABHandler = static_cast<ActionButton::GetInCar*>( GetActionButtonManager()->GetActionByIndex(id) );
rAssert( dynamic_cast<ActionButton::GetInCar*>( pABHandler ) != NULL );
rAssert( pABHandler );
pABHandler->SetVehicleId(slot);
// leave AI untouched! Their triggers remain OFF!
vehicle->ActivateTriggers(true);
//-----------
// add to dsg
//-----------
GetRenderManager()->pWorldScene()->Add((DynaPhysDSG*)vehicle);
vehicle->GetCollisionAreaIndexAndAddSelf();
int curWorldRenderLayer = GetRenderManager()->rCurWorldRenderLayer();
vehicle->SetRenderLayerEnum((RenderEnums::LayerEnum)curWorldRenderLayer);
// temp - for car on car collisions
// TODO - remove
// until the vehicles are moving around in the scenegraph, we need to make sure the cars have a collision pair for each other
/*
for(i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
if(mActiveVehicleList[i] != 0 && i != slot)
{
vehicle->AddToOtherCollisionArea(mActiveVehicleList[i]->mCollisionAreaIndex);
}
}
*/
//
// Notify the world about new user vehicles
//
if( vehicle->mVehicleType == VT_USER )
{
GetEventManager()->TriggerEvent( EVENT_USER_VEHICLE_ADDED_TO_WORLD, vehicle );
}
// april 22, 2003
// new
// vehicle will hold it's slot.
vehicle->mVehicleCentralIndex = slot;
vehicle->AddRef();
return slot;
}
//=============================================================================
// VehicleCentral::RemoveVehicleFromActiveList
//=============================================================================
// Description: Comment
//
// returns whether or not it was even there in the first place
//
//
// Parameters: (Vehicle* vehicle)
//
// Return: bool
//
//=============================================================================
bool VehicleCentral::RemoveVehicleFromActiveList(Vehicle* vehicle)
{
int i;
for(i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
if(mActiveVehicleList[i] == vehicle)
{
//Chuck: If car getting dumped was the last car used by the player
//set the mCurrentVehicle to NULL
// greg
// jan 4, 2003
//
// TODO
// not sure if we want this code
// mCurrentVehicle should be updated elsewhere
// PHONEBOOTH CAR SHOULD REPLACE DEFAULT VEHICLE.
// this change is going in rsn
//if (GetGameplayManager()->GetCurrentVehicle() == vehicle)
//{
// Vehicle* p_vehicle = GetGameplayManager()->GetVehicle(GetGameplayManager()->mDefaultVehicle);
// GetGameplayManager()->SetCurrentVehicle(p_vehicle);
//}
// later in the same day
//
// GameplayManager::DumpCurrentCar ()
// now sets mCurrentVehicle to NULL as the name would imply
mActiveVehicleList[i] = 0;
mNumActiveVehicles--;
// make sure controller slot doesn't have junk left lying around in it.
if( mActiveVehicleControllerList[i] )
{
mActiveVehicleControllerList[i]->Release();
}
//mActiveVehicleControllerList[i] = NULL;
mActiveVehicleControllerList[i] = spGenericAI;
mActiveVehicleControllerList[i]->AddRef();
// !! need to remove this from any other vehicles mCurrentDynamics list
//
// what an ugly pain in the ass:
GetWorldPhysicsManager()->RemoveFromAnyOtherCurrentDynamicsListAndCollisionArea(vehicle);
vehicle->RemoveSelfAndFreeCollisionAreaIndex();
//----------------
// remove from DSG
//----------------
int& curRenderLayer = GetRenderManager()->rCurWorldRenderLayer();
int orgRenderLayer = curRenderLayer;
// swtich to the vehicle's render layer
curRenderLayer = vehicle->GetRenderLayerEnum();
//Chuck: if we're removing the car lets check if there is a AI NPC driver in that car
if(vehicle->GetDriver() != NULL)
{
vehicle->GetDriver()->RemoveFromWorldScene();
}
GetRenderManager()->pWorldScene()->Remove(/*(DynaPhysDSG*)*/ vehicle);
// restore the orignal render layer
curRenderLayer = orgRenderLayer;
// hack
//vehicle->Release();
// leave AI untouched! Their triggers remain OFF!
vehicle->ActivateTriggers(false);
//
// Notify the world about deleted user vehicles
//
if( vehicle->mVehicleType == VT_USER )
{
GetEventManager()->TriggerEvent( EVENT_USER_VEHICLE_REMOVED_FROM_WORLD, vehicle );
}
// stop tracking AI...
if( GetGameFlow()->GetCurrentContext() != CONTEXT_SUPERSPRINT )
{
GetTriggerVolumeTracker()->UnregisterAI( vehicle );
}
vehicle->mVehicleCentralIndex = -1;
vehicle->Release();
return true;
}
/*
else if(mActiveVehicleList[i])
{
// this isn't super-efficient but it's only temporary and should stop Darryl's whining
// try and remove from all other collision areas just in case it's in there...
GetWorldPhysicsManager()->mCollisionManager->
RemoveCollisionObject(vehicle->mSimStateArticulated->GetCollisionObject(), mActiveVehicleList[i]->mCollisionAreaIndex);
}
*/
}
return false;
}
//=============================================================================
// VehicleCentral::KillEmAll
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::KillEmAll()
{
// not sure if I should keep this method around, because whoever creates the
// vehicle should destroy it
//
// but the method name is so fucking cool....
}
/*
//=============================================================================
// VehicleCentral::Suspend
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::Suspend()
{
mSuspended = true;
}
//=============================================================================
// VehicleCentral::Resume
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::Resume()
{
mSuspended = false;
}
*/
//=============================================================================
// VehicleCentral::GetVehicle
//=============================================================================
// Description: Comment
//
// Parameters: ( int id )
//
// Return: Vehicle
//
//=============================================================================
Vehicle* VehicleCentral::GetVehicle( int id ) const
{
//rAssert( id < this->mNumActiveVehicles );
return this->mActiveVehicleList[ id ];
}
//=============================================================================
// VehicleCentral::SetVehicleController
//=============================================================================
// Description: Comment
//
// Parameters: ( int id, VehicleController* pVehicleController )
//
// Return: void
//
//=============================================================================
void VehicleCentral::SetVehicleController( int id, VehicleController* pVehicleController )
{
if ( id >= 0 && id < MAX_ACTIVE_VEHICLES )
{
//rAssert( id < this->mNumActiveVehicles ); // don't think this is necessary anymore
if ( pVehicleController )
{
pVehicleController->Init();
}
else
{
if ( mActiveVehicleControllerList[ id ] )
{
mActiveVehicleControllerList[ id ]->Shutdown();
}
pVehicleController = spGenericAI;
}
tRefCounted::Assign( mActiveVehicleControllerList[ id ], pVehicleController );
}
else
{
rAssertMsg( 0, "SetVehicleController - id out of range" );
}
}
//Triage hack, only for demo mode, or until Greg actually
//addrefs and releases --dm 12/01/02
VehicleController* VehicleCentral::RemoveVehicleController( int mAIIndex )
{
if ( mActiveVehicleControllerList[ mAIIndex ] )
{
VehicleController* FoundVehicleController = mActiveVehicleControllerList[ mAIIndex ];
mActiveVehicleControllerList[ mAIIndex ] = 0;
return FoundVehicleController;
}
return NULL;
}
//=============================================================================
// VehicleCentral::GetVehicleController
//=============================================================================
// Description: Comment
//
// Parameters: ( int id )
//
// Return: VehicleController
//
//=============================================================================
VehicleController* VehicleCentral::GetVehicleController( int id ) const
{
if( 0 <= id && id < MAX_ACTIVE_VEHICLES )
{
if( mActiveVehicleControllerList[ id ] == spGenericAI )
{
return NULL;
}
return mActiveVehicleControllerList[ id ];
}
return NULL;
}
//=============================================================================
// VehicleCentral::GetVehicleId
//=============================================================================
// Description: Comment
//
// Parameters: ( Vehicle* pVehicle )
//
// Return: int
//
//=============================================================================
int VehicleCentral::GetVehicleId( Vehicle* pVehicle, bool checkStrict ) const
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if(pVehicle == mActiveVehicleList[i])
{
return i;
}
}
if(checkStrict)
{
rAssertMsg( false, "Vehicle not found in Vehicle Database!\n" );
}
return (int)-1;
}
//=============================================================================
// VehicleCentral::PreSubstepUpdate
//=============================================================================
// Description: Comment
//
// Parameters: ( )
//
// Return: void
//
//=============================================================================
void VehicleCentral::PreSubstepUpdate( float dt )
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
Vehicle* vehicle = mActiveVehicleList[i];
if( vehicle ) // TODO - wrap with render layer test
{
vehicle->PreSubstepUpdate(dt);
// Update controller
VehicleController* vController = mActiveVehicleControllerList[i];
if( vController != 0 )
{
vController->Update( dt );
float test = vController->GetGas();
//?
// safe to just apply these as-is to vehicle?
vehicle->SetGas(test);
test = vController->GetBrake( );
vehicle->SetBrake( test );
test = vController->GetThrottle();
if(test > 0.1f)
{
vehicle->SetGas( test );
}
if(test < -0.1f)
{
vehicle->SetBrake( -test );
}
//This sucks.
bool isWheel = false;
test = vController->GetSteering( isWheel );
// test stick and dpad and set highest fabs
float left = 0.0f;
if( vController->GetSteerLeft() )
{
left = vController->GetSteerLeft( );
}
float right = 0.0f;
if( vController->GetSteerRight() )
{
right = vController->GetSteerRight( );
}
if(rmt::Fabs(test) > left && rmt::Fabs(test) > right)
{
// use stick value
vehicle->SetWheelTurnAngle(test, isWheel, dt);
}
else if(right > left)
{
vehicle->SetWheelTurnAngle(right, false, dt);
}
else
{
vehicle->SetWheelTurnAngle(-left, false, dt);
}
/*
// only human controlled vehicles will return a pointer here
if(vController->GetSteerLeft())
{
float left = vController->GetSteerLeft( );
if(test <= 0.0f && left > rmt::Fabs(test))
{
vehicle->SetWheelTurnAngle(-left, false, dt);
}
}
if(vController->GetSteerRight())
{
float right = vController->GetSteerRight( );
if(test >= 0.0f && right > test)
{
vehicle->SetWheelTurnAngle(right, false, dt);
}
}
*/
test = vController->GetReverse( );
vehicle->SetReverse(test);
test = vController->GetHandBrake();
vehicle->SetEBrake(test, dt);
if( GetCheatInputSystem()->IsCheatEnabled(CHEAT_ID_CAR_JUMP_ON_HORN) &&
vehicle == GetAvatarManager()->GetAvatarForPlayer(0)->GetVehicle() ) // vehicle->mVehicleType == VT_USER )
{
test = vController->GetHorn( );
if(test > 0.1f)
{
vehicle->JumpOnHorn(test);
}
}
if( vController->GetHorn() > 0.0f )
{
// Only the player vehicle's controller uses Set/GetHorn.
// AI cars never at any time set the Horn value.
if( vehicle == GetAvatarManager()->GetAvatarForPlayer(0)->GetVehicle() ||
::GetGameplayManager()->GetGameType() == GameplayManager::GT_SUPERSPRINT )
{
// if in a certain game type, use the horn button for speedboost
if( ::GetGameplayManager()->GetGameType() == GameplayManager::GT_SUPERSPRINT )
{
// may or may not do turbo depending on if turbo is available..
vehicle->TurboOnHorn();
}
else
{
// outside of Supersprint context, we want to fire off an event
// so that traffic can honk back and peds can panick.
GetEventManager()->TriggerEvent( EVENT_PLAYER_VEHICLE_HORN, vehicle );
}
}
}
}
else
{
vehicle->SetGas(0.0f);
vehicle->SetBrake(0.0f);
vehicle->SetWheelTurnAngle(0.0f, false, dt);
vehicle->SetReverse(0.0f);
vehicle->SetEBrake(0.0f, dt);
}
//
// [Dusit Matthew Eakkachaichanvet: Dec 10, 2002]
// ok, the controller has been updated and knows of
// last frame's collision with a vehicle, so
// we can clear this value now.
//
vehicle->mCollidedWithVehicle = false;
vehicle->mNormalizedMagnitudeOfVehicleHit = 0.0f;
vehicle->mWasHitByVehicle = false;
}
}
}
//=============================================================================
// VehicleCentral::Update
//=============================================================================
// Description: Comment
//
// Parameters: (float dt)
//
// Return: void
//
//=============================================================================
void VehicleCentral::Update(float dt)
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
//rAssert( mActiveVehicleList[ i ] );
if( mActiveVehicleList[i] &&
(GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum()))
{
BEGIN_PROFILE("ActiveVehicle->Update")
mActiveVehicleList[i]->Update( dt );
END_PROFILE("ActiveVehicle->Update")
//rAssertMsg( mActiveVehicleList[i] != NULL, "VehicleCentral::Update - trying to add a null vehicle* pointer!" );
if ( mActiveVehicleList[i] != NULL )
{
if(mActiveVehicleList[i]->GetLocomotionType() == VL_PHYSICS)
{
BEGIN_PROFILE("WorldPhysManager()->UpdateDyna")
GetWorldPhysicsManager()->UpdateDynamicObjects(dt, mActiveVehicleList[i]->mCollisionAreaIndex);
GetWorldPhysicsManager()->UpdateAnimCollisions(dt, mActiveVehicleList[i]->mCollisionAreaIndex);
END_PROFILE("WorldPhysManager()->UpdateDyna")
// Temp removed this because objects were being updated twice.
// more important (for me) to have the character update anim objects.
//
// TBJ [8/27/2002]
//
//GetWorldPhysicsManager()->UpdateAnimCollisions(dt, mActiveVehicleList[i]->mCollisionAreaIndex);
}
}
}
}
}
//=============================================================================
// VehicleCentral::ClearSpot
//=============================================================================
// Description: Comment
//
// Parameters: (rmt::Vector& point, float radius)
//
// Return: void
//
//=============================================================================
void VehicleCentral::ClearSpot(rmt::Vector& point, float radius, Vehicle* skipCar)
{
rAssert(0); // don't call this
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if( mActiveVehicleList[i] &&
GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum() &&
mActiveVehicleList[i] != skipCar)
{
rmt::Vector carPosition = mActiveVehicleList[i]->rPosition();
rmt::Vector vectorToCar = carPosition;
vectorToCar.Sub(point);
float carsWheelBase = mActiveVehicleList[i]->GetWheelBase();
float dist = vectorToCar.Magnitude();
if(dist - carsWheelBase < radius)
{
// this car has to move back
float amount = radius - (dist - carsWheelBase);
// first test
// blast it back by some ratio of amount?
rmt::Vector fix = vectorToCar;
fix.NormalizeSafe();
fix.Scale(amount);
carPosition.Add(fix);
// quick test for fun and safety
carPosition.y += 2.0f;
float ang = mActiveVehicleList[i]->GetFacingInRadians();
rmt::Matrix m;
m.Identity();
m.FillRotateXYZ( 0.0f, ang, 0.0f );
m.FillTranslate(carPosition);
mActiveVehicleList[i]->SetTransform(m);
/*
rmt::Vector& linearVelocity = mActiveVehicleList[i]->mSimStateArticulated->GetLinearVelocity();
vectorToCar.NormalizeSafe();
static float magicshit = 1.0f;
vectorToCar.Scale(amount * magicshit);
linearVelocity = vectorToCar;
*/
}
}
}
}
//=============================================================================
// VehicleCentral::PostSubstepUpdate
//=============================================================================
// Description: Comment
//
// Parameters: (float dt)
//
// Return: void
//
//=============================================================================
void VehicleCentral::PostSubstepUpdate(float dt)
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
//rAssert( mActiveVehicleList[ i ] );
if( mActiveVehicleList[i] &&
GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum())
{
mActiveVehicleList[i]->PostSubstepUpdate(dt);
}
}
}
//=============================================================================
// VehicleCentral::PreCollisionPrep
//=============================================================================
// Description: Comment
//
// Parameters: ( )
//
// Return: void
//
//=============================================================================
void VehicleCentral::PreCollisionPrep(float dt, bool firstSubstep)
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if( mActiveVehicleList[i] &&
GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum())
{
mActiveVehicleList[ i ]->PreCollisionPrep(dt, firstSubstep);
}
}
}
//=============================================================================
// VehicleCentral::SubmitStatics
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::SubmitStatics()
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if( mActiveVehicleList[i] &&
GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum())
{
if(1)
//if(mActiveVehicleList[i]->GetLocomotionType() == VL_PHYSICS)
{
rmt::Vector position = mActiveVehicleList[i]->GetPosition();
// at 200kmh, we cover 55.5 m/s
// a long frame would be 50ms...
//
// at that rate we'd cover 2.775 m
// hmm.... ferrini wheel base is approx 3m
//float radius = mActiveVehicleList[i]->GetWheelBase() * 3.0f; // TODO - what magic number?
float radius = mActiveVehicleList[i]->GetWheelBase() * 2.0f; // TODO - what magic number?
int collisionAreaIndex = mActiveVehicleList[i]->mCollisionAreaIndex;
rAssert(collisionAreaIndex != -1);
Avatar* playerAvatar = GetAvatarManager()->GetAvatarForPlayer(0);
Vehicle* playerVehicle = 0;
if(playerAvatar)
{
playerVehicle = playerAvatar->GetVehicle();
}
if(playerVehicle && mActiveVehicleList[i] == playerVehicle)
{
GetWorldPhysicsManager()->SubmitStaticsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), true);
GetWorldPhysicsManager()->SubmitFencePiecesPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), true);
}
else
{
GetWorldPhysicsManager()->SubmitStaticsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), false);
GetWorldPhysicsManager()->SubmitFencePiecesPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState());
}
// TODO - should probably only do this one if it's a human driver or AI ... ie. not traffic bouncing around
//GetWorldPhysicsManager()->SubmitFencePiecesPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState());
}
else
{
/*
// an active vehicle, but not VL_PHYSICS
// so we want to do a DSG query and cleanup of our collision area if necessary
rmt::Vector position = mActiveVehicleList[i]->GetPosition();
float radius = mActiveVehicleList[i]->GetWheelBase() * 2.0f; // TODO - what magic number?
int collisionAreaIndex = mActiveVehicleList[i]->mCollisionAreaIndex;
rAssert(collisionAreaIndex != -1);
GetWorldPhysicsManager()->CleanOnlyStaticsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState());
// TODO - should probably only do this one if it's a human driver or AI ... ie. not traffic bouncing around
GetWorldPhysicsManager()->SubmitFencePiecesPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState());
*/
}
}
}
}
//=============================================================================
// VehicleCentral::SubmitDynamics
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::SubmitDynamics()
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if( mActiveVehicleList[i] &&
GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum())
{
// new
// call this for all (one) VT_USER cars first
//if(mActiveVehicleList[i]->GetLocomotionType() == VL_PHYSICS && mActiveVehicleList[i]->mVehicleType == VT_USER)
if(mActiveVehicleList[i]->mVehicleType == VT_USER)
{
rmt::Vector position = mActiveVehicleList[i]->GetPosition();
//float radius = mActiveVehicleList[i]->GetWheelBase() * 3.0f; // TODO - what magic number?
float radius = mActiveVehicleList[i]->GetWheelBase() * 2.0f; // TODO - what magic number?
int collisionAreaIndex = mActiveVehicleList[i]->mCollisionAreaIndex;
rAssert(collisionAreaIndex != -1);
Avatar* playerAvatar = GetAvatarManager()->GetAvatarForPlayer(0);
Vehicle* playerVehicle = 0;
if(playerAvatar)
{
playerVehicle = playerAvatar->GetVehicle();
}
if(playerVehicle && mActiveVehicleList[i] == playerVehicle)
{
GetWorldPhysicsManager()->SubmitDynamicsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), true);
}
else
{
GetWorldPhysicsManager()->SubmitDynamicsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), false);
}
}
}
}
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if( mActiveVehicleList[i] &&
GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum())
{
//if(mActiveVehicleList[i]->GetLocomotionType() == VL_PHYSICS && mActiveVehicleList[i]->mVehicleType != VT_USER)
if(mActiveVehicleList[i]->mVehicleType != VT_USER)
{
rmt::Vector position = mActiveVehicleList[i]->GetPosition();
//float radius = mActiveVehicleList[i]->GetWheelBase() * 3.0f; // TODO - what magic number?
float radius = mActiveVehicleList[i]->GetWheelBase() * 2.0f; // TODO - what magic number?
int collisionAreaIndex = mActiveVehicleList[i]->mCollisionAreaIndex;
rAssert(collisionAreaIndex != -1);
Avatar* playerAvatar = GetAvatarManager()->GetAvatarForPlayer(0);
Vehicle* playerVehicle = 0;
if(playerAvatar)
{
playerVehicle = playerAvatar->GetVehicle();
}
if(playerVehicle && mActiveVehicleList[i] == playerVehicle)
{
GetWorldPhysicsManager()->SubmitDynamicsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), true);
}
else
{
GetWorldPhysicsManager()->SubmitDynamicsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), false);
}
//GetWorldPhysicsManager()->SubmitDynamicsPseudoCallback(position, radius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState(), false);
}
}
}
}
//=============================================================================
// VehicleCentral::SubmitAnimCollisions
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void VehicleCentral::SubmitAnimCollisions()
{
int i;
for ( i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if( mActiveVehicleList[i] &&
GetRenderManager()->rCurWorldRenderLayer() == mActiveVehicleList[i]->GetRenderLayerEnum())
{
if(1)
//if(mActiveVehicleList[i]->GetLocomotionType() == VL_PHYSICS)
{
rmt::Vector position = mActiveVehicleList[i]->GetPosition();
//float collradius = mActiveVehicleList[i]->GetWheelBase() * 3.0f; // TODO - what magic number?
float collradius = mActiveVehicleList[i]->GetWheelBase() * 2.0f; // TODO - what magic number?
int collisionAreaIndex = mActiveVehicleList[i]->mCollisionAreaIndex;
rAssert(collisionAreaIndex != -1);
GetWorldPhysicsManager()->SubmitAnimCollisionsPseudoCallback(position, collradius, collisionAreaIndex, mActiveVehicleList[i]->GetSimState());
float updateradius = collradius * 1.0f; //? TODO - what magic number
GetWorldPhysicsManager()->SubmitAnimCollisionsForUpdateOnly(position, updateradius, collisionAreaIndex);
}
}
}
}
//=============================================================================
// VehicleCentral::GetVehicleByName
//=============================================================================
// Description: Comment
//
// Parameters: ( const char* name )
//
// Return: Vehicle
//
//=============================================================================
Vehicle* VehicleCentral::GetVehicleByName( const char* name ) const
{
return GetVehicleByUID( tEntity::MakeUID( name ) );
}
/*
==============================================================================
VehicleCentral::GetVehicleByUID
==============================================================================
Description: Comment
Parameters: ( tUID uid )
Return: Vehicle
=============================================================================
*/
Vehicle* VehicleCentral::GetVehicleByUID( tUID uid ) const
{
Vehicle* vehicle = 0;
for( int i = 0; i < MAX_ACTIVE_VEHICLES; i++ )
{
if ( mActiveVehicleList[ i ] != 0 )
{
if( uid == tEntity::MakeUID( mActiveVehicleList[ i ]->GetName() ) )
{
vehicle = mActiveVehicleList[ i ];
break;
}
}
}
return vehicle;
}
//=============================================================================
// VehicleCentral::OnProcessRequestsComplete
//=============================================================================
// Description: Comment
//
// Parameters: ( void* pUserData )
//
// Return: void
//
//=============================================================================
void VehicleCentral::OnProcessRequestsComplete( void* pUserData )
{
Character* theDriver;
Vehicle* vehicle = GetCurrentVehicleUnderConstruction();
rAssert( vehicle );
vehicle->CalculateValuesBasedOnDesignerParams();
SetupDriver(vehicle);
theDriver = vehicle->GetDriver();
if( theDriver != NULL )
{
//
// Despite the name, send this for every vehicle load. The dialogue
// system keeps a flag to determine which ones come from phone booths,
// and throws the rest of 'em out. Not pretty, but we're going final.
// -- Esan
//
GetEventManager()->TriggerEvent( EVENT_PHONE_BOOTH_NEW_VEHICLE_SELECTED, theDriver );
}
else
{
GetEventManager()->TriggerEvent( EVENT_PHONE_BOOTH_CANCEL_RIDEREPLY_LINE );
}
//Clear the head.
mVehicleUnderConstruction[mCurrentVehicleUnderContructionHead] = NULL;
mCurrentVehicleUnderContructionHead = (mCurrentVehicleUnderContructionHead + 1) % MAX_ACTIVE_VEHICLES;
if ( mCurrentVehicleUnderContructionHead == mCurrentVehicleUnderConstructionTail )
{
rAssert( mVehicleUnderConstruction[mCurrentVehicleUnderContructionHead] == NULL );
}
}
void VehicleCentral::ActivateVehicleTriggers(bool active)
{
if(active == mbVehicleTriggersActive)
{
return;
}
mbVehicleTriggersActive = active;
Vehicle* v = NULL;
if( mbVehicleTriggersActive )
{
for(int i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
v = mActiveVehicleList[i];
if(v)
{
v->ActivateTriggers(true);
}
}
}
else
{
for(int i = 0; i < MAX_ACTIVE_VEHICLES; i++)
{
v = mActiveVehicleList[i];
if( v )
{
v->ActivateTriggers(false);
}
}
}
}
void VehicleCentral::ClearSuppressedDrivers(void)
{
for(unsigned i = 0; i < mSuppressedDriverCount; i++)
{
mSuppressedDrivers[i].SetText(NULL);
}
mSuppressedDriverCount = 0;
}
void VehicleCentral::AddSuppressedDriver(const char* name)
{
rAssert(mSuppressedDriverCount < MAX_SuppressED_DRIVERS);
mSuppressedDrivers[mSuppressedDriverCount++].SetText(name);
}
void VehicleCentral::RemoveSuppressedDriver(const char* name)
{
tUID uid = tEntity::MakeUID(name);
for(unsigned i = 0; i < mSuppressedDriverCount; i++)
{
if(mSuppressedDrivers[i].GetUID() == uid)
{
mSuppressedDrivers[i].SetUID((tUID)0);
return;
}
}
}
bool VehicleCentral::IsDriverSuppressed(const char* name)
{
tUID uid = tEntity::MakeUID(name);
for(unsigned i = 0; i < mSuppressedDriverCount; i++)
{
if(mSuppressedDrivers[i].GetUID() == uid)
return true;
}
return false;
}
void VehicleCentral::SetupDriver(Vehicle* vehicle)
{
if(vehicle->GetDriver())
{
if((vehicle->GetDriver() != GetCharacterManager()->GetCharacter(0)) && (vehicle->GetDriver()->GetRole() != Character::ROLE_PEDESTRIAN))
{
GetCharacterManager()->RemoveCharacter(vehicle->GetDriver());
vehicle->SetDriver(NULL);
}
}
if(vehicle->mDriverInit != FORCE_NO_DRIVER)
{
if((vehicle->GetDriverName()[0] != 0))
{
if(strcmp(vehicle->GetDriverName(),"phantom") == 0)
{
vehicle->SetPhantomDriver(true);
}
else
{
if((strcmp(vehicle->GetDriverName(),"none") != 0) &&
((vehicle->mDriverInit == FORCE_DRIVER) || !IsDriverSuppressed(vehicle->GetDriverName())))
{
char uniqueName[16];
sprintf(uniqueName, "d_%s", vehicle->GetDriverName());
Character* character = NULL;
character = GetCharacterManager()->GetCharacterByName(uniqueName);
if(character && ((character->GetTargetVehicle() == vehicle) || (character->GetTargetVehicle() == NULL)))
{
GetCharacterManager()->RemoveCharacter(character);
}
character = GetCharacterManager()->AddCharacter(CharacterManager::NPC, uniqueName, vehicle->GetDriverName(), "npd", "");
static_cast<NPCController*>(character->GetController())->TransitToState(NPCController::NONE);
character->SetTargetVehicle( vehicle );
character->AddToWorldScene();
character->GetStateManager()->SetState<CharacterAi::InCar>();
vehicle->SetDriver(character);
character->SetRole(Character::ROLE_DRIVER);
}
}
}
}
}
//chuck adding this method so we can determine if car is still underconstruction.
bool VehicleCentral::IsCarUnderConstruction(const char* name)
{
//unsigned int pListPtr = mCurrentVehicleUnderContructionHead;
for(int i=0;i<MAX_ACTIVE_VEHICLES;i++)
{
if (mVehicleUnderConstruction[i] != NULL)
{
if( strcmp(mVehicleUnderConstruction[i]->GetName(),name) == 0)
{
return true;
}
}
}
return false;
}
bool VehicleCentral::IsCarUnderConstruction(const Vehicle* vehicle)
{
for(int i=0;i<MAX_ACTIVE_VEHICLES;i++)
{
if (mVehicleUnderConstruction[i] != NULL)
{
if( mVehicleUnderConstruction[i] == vehicle )
{
return true;
}
}
}
return false;
}
VehicleAI* VehicleCentral::GetVehicleAI( Vehicle* vehicle )
{
if( vehicle )
{
//////////////////////////
// if Demo context, it's ok to fetch AI for
// non VT_AI types. Otherwise, we must boot!!
//
// Note:
// Supersprint doesn't worry about these, the AI cars should
// be VT_AI...
//
if( GetGameFlow()->GetCurrentContext() != CONTEXT_DEMO &&
vehicle->mVehicleType != VT_AI )
{
return NULL;
}
int id = GetVehicleCentral()->GetVehicleId( vehicle );
VehicleController* controller = GetVehicleCentral()->GetVehicleController( id );
if( controller )
{
rAssert( dynamic_cast<VehicleAI*>( controller ) );
return static_cast<VehicleAI*>( controller );
}
}
return NULL;
}
void VehicleCentral::DetachAllCollectibles()
{
for ( int i = 0 ; i < GetNumVehicles() ; i++ )
{
Vehicle* v = GetVehicle( i );
if ( v != NULL )
{
v->DetachCollectible( rmt::Vector(0,0,0), false );
}
}
}