The-Simpsons-Hit-and-Run/game/code/camera/supercamcentral.cpp

2358 lines
70 KiB
C++

//=============================================================================
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
//
// File: supercamcentral.cpp
//
// Description: Implement SuperCamCentral
//
// History: 03/04/2002 + Created -- Cary Brisebois
//
//=============================================================================
//========================================
// System Includes
//========================================
// Foundation Tech
//These are included in the precompiled headers on XBOX and GC
#include <raddebug.hpp>
#include <raddebugwatch.hpp>
#include <stdlib.h>
#include <simcollision/collisionobject.hpp>
#include <simcollision/collisionvolume.hpp>
#include <simcollision/collisionmanager.hpp>
#include <simcommon/simstate.hpp>
#include <p3d/pointcamera.hpp>
#include <p3d/view.hpp>
//========================================
// Project Includes
//========================================
#include <camera/SuperCam.h>
#include <camera/SuperCamCentral.h>
#include <camera/animatedcam.h>
#include <camera/conversationcam.h>
#include <camera/frustrumdrawable.h>
#include <camera/isupercamtarget.h>
#include <camera/supercamcontroller.h>
#include <camera/followcam.h>
#include <camera/wrecklesscam.h>
#ifdef RAD_WIN32
#include <camera/pccam.h>
#endif
#include <data/gamedatamanager.h>
#include <render/RenderManager/RenderManager.h>
#include <render/RenderManager/RenderLayer.h>
#include <memory/srrmemory.h>
#include <input/inputmanager.h>
#include <input/controller.h>
#include <debug/profiler.h>
#include <meta/fovlocator.h>
#include <meta/eventlocator.h>
#include <worldsim/physicsairef.h>
#include <worldsim/worldphysicsmanager.h>
#include <worldsim/redbrick/vehicle.h>
#include <worldsim/character/charactermanager.h>
#include <worldsim/character/character.h>
#include <events/eventmanager.h>
#include <events/eventdata.h>
#include <render/IntersectManager/IntersectManager.h>
#include <mission/gameplaymanager.h>
#include <mission/charactersheet/charactersheetmanager.h>
#include <main/game.h>
#include <cheats/cheatinputsystem.h>
//*****************************************************************************
//
// Global Data, Local Data, Local Classes
//
//*****************************************************************************
//#define PRINTCAMERANAMES
const rmt::Vector DEBUG_NAME_POS(0.8f, 0.8f, 0);
//Debug Camera settings.
const float DEBUG_CAM_XZ_ANGLE = 0.0f;
const float DEBUG_CAM_Y_ANGLE = 0.03f;
const float DEBUG_CAM_DIST = 70.0f;
const float DEBUG_CAM_FOV = 90.0f;
const float DEBUG_CAM_ASPECT = 4.0f / 3.0f;
const float DEBUG_CAM_NEAR = 0.1f;
const float DEBUG_CAM_FAR = 700.0f;
SuperCam::Type CAMERAS_FOR_DRIVING[] =
{
SuperCam::NEAR_FOLLOW_CAM,
SuperCam::FAR_FOLLOW_CAM,
SuperCam::BUMPER_CAM,
//Start of cheat cams
SuperCam::COMEDY_CAM,
SuperCam::WRECKLESS_CAM,
SuperCam::CHASE_CAM,
SuperCam::KULL_CAM,
SuperCam::TRACKER_CAM,
SuperCam::DEBUG_CAM
};
const int NUM_CAMERAS_FOR_DRIVING = 9;
// this must be less than or equal to NUM_CAMERAS_FOR_DRIVING
//
const int NUM_CAMERAS_FOR_DRIVING_WITHOUT_CHEAT = 3;
SuperCam::Type CAMERAS_FOR_WALKING[] =
{
SuperCam::WALKER_CAM,
#ifdef RAD_WIN32
SuperCam::PC_CAM,
#endif
SuperCam::DEBUG_CAM,
SuperCam::KULL_CAM
};
#ifdef RAD_WIN32
const int NUM_CAMERAS_FOR_WALKING = sizeof(CAMERAS_FOR_WALKING)/sizeof(SuperCam::Type);
// this must be less than or equal to NUM_CAMERAS_FOR_WALKING
//
const int NUM_CAMERAS_FOR_WALKING_WITHOUT_CHEAT = 2;
#else
const int NUM_CAMERAS_FOR_WALKING = 3;
// this must be less than or equal to NUM_CAMERAS_FOR_WALKING
//
const int NUM_CAMERAS_FOR_WALKING_WITHOUT_CHEAT = 1;
#endif
SuperCam::Type SUPER_SPRINT_CAMERAS[] =
{
SuperCam::NEAR_FOLLOW_CAM,
SuperCam::FAR_FOLLOW_CAM,
SuperCam::BUMPER_CAM,
SuperCam::COMEDY_CAM,
SuperCam::WRECKLESS_CAM
#ifndef RAD_RELEASE
,SuperCam::KULL_CAM
#endif
};
const int NUM_SUPERSPRINT_CAMS =
sizeof( SUPER_SPRINT_CAMERAS ) / sizeof( SUPER_SPRINT_CAMERAS[ 0 ] );
const unsigned int DEFAULT_CAM_SWITCH_DELAY = 0; //milliseconds
unsigned char SuperCamCentral::mTotalSuperCamCentrals = 0;
const char* SuperCamCentral::CAMERA_INVENTORY_SECTION = "CameraInventorySection";
FollowCamDataChunk SuperCamCentral::mFollowCamDataChunks[ MAX_DATA_CHUNKS ];
unsigned int SuperCamCentral::mNumUsedFDC = 0;
#ifdef DEBUGWATCH
void ToggleDebugViewCallBack( void* userData )
{
SuperCamCentral* ssc = (SuperCamCentral*)userData;
ssc->ToggleDebugView();
}
void ToggleCameraForwardsCallBack( void* userData )
{
SuperCamCentral* ssc = (SuperCamCentral*)userData;
ssc->ToggleSuperCam( true );
}
void ToggleCameraBackwardsCallBack( void* userData )
{
SuperCamCentral* ssc = (SuperCamCentral*)userData;
ssc->ToggleSuperCam( false );
}
void ToggleBurnoutCallBack( void* userData )
{
static bool gBurnout = false;
if ( !gBurnout )
{
GetEventManager()->TriggerEvent( EVENT_BURNOUT );
gBurnout = true;
}
else
{
GetEventManager()->TriggerEvent( EVENT_BURNOUT_END );
gBurnout = false;
}
}
void ToggleCameraCut( void* userData )
{
SuperCamCentral* ssc = (SuperCamCentral*)userData;
ssc->DoCameraCut();
}
#endif
//*****************************************************************************
//
// Public Member Functions
//
//*****************************************************************************
//=============================================================================
// SuperCamCentral::SuperCamCentral
//=============================================================================
// Description: Constructor.
//
// Parameters: None.
//
// Return: N/A.
//
//=============================================================================
SuperCamCentral::SuperCamCentral() :
mCollisionAreaIndex(-1),
mActiveSuperCam( NULL ),
mActiveSuperCamIndex( 0 ),
mNumRegisteredSuperCams( 0 ),
mCamera( NULL ),
mTarget( NULL ),
#ifdef SUPERCAM_DEBUG
mDebugXZAngle( 0.0f ),
mDebugYAngle( rmt::PI ),
mDebugMagnitude( DEBUG_CAM_DIST ),
#endif
mCurrentFOVLocator( NULL ),
mDoCameraCut( false ),
mChanceToBurnout( 10 ),
mCameraSimState( NULL ),
mCameraCollisionFudge( 1.05f ),
mController( NULL ),
mControllerHandle( -1 ),
mWrecklessCount( 0 ),
mPreferredFollowCam( FollowCam::FAR_FOLLOW_CAM ),
mInitialCamera(false),
mIsInvertedCameraEnabled( false ),
mJumpCamsEnabled( true ),
mCameraToggling( false ),
mNastyHypeCamHackEnabled( false )
{
MEMTRACK_PUSH_GROUP( "SuperCamCentral" );
//Each SuperCamCentral is uniquely numbered.
//These numbers correspond to players.
mMyNumber = mTotalSuperCamCentrals;
++mTotalSuperCamCentrals;
unsigned int i;
for ( i = 0; i < MAX_CAMERAS; ++i )
{
mSuperCameras[ i ] = NULL;
}
#ifdef RAD_GAMECUBE
HeapMgr()->PushHeap( GMA_GC_VMM );
#else
HeapMgr()->PushHeap( GMA_PERSISTENT );
#endif
#ifdef SUPERCAM_DEBUG
mDebugCamera = new tPointCamera();
mDebugCamera->AddRef();
char camName[256];
sprintf( camName, "SuperCamCentral %d DebugCam", mMyNumber );
mDebugCamera->SetName( camName );
mFrustrumDrawable = new FrustrumDrawable();
mFrustrumDrawable->AddRef();
char frustName[256];
sprintf( frustName, "FrustrumDrawable%d", mMyNumber );
mFrustrumDrawable->SetName( frustName );
#endif
GetEventManager()->AddListener( this, EVENT_ENTER_INTERIOR_END );
GetEventManager()->AddListener( this, EVENT_BURNOUT );
GetEventManager()->AddListener( this, EVENT_BURNOUT_END );
GetEventManager()->AddListener( this, EVENT_CAMERA_SHAKE );
GetGameDataManager()->RegisterGameData( this, 1, "Super Cam Central" );
#ifdef RAD_GAMECUBE
HeapMgr()->PopHeap( GMA_GC_VMM );
#else
HeapMgr()->PopHeap( GMA_PERSISTENT );
#endif
#ifdef DEBUGWATCH
char player[256];
sprintf( player, "SuperCamCentral\\Player%d", mMyNumber );
radDbgWatchAddFunction( "Toggle Debug View", &ToggleDebugViewCallBack, this, player );
radDbgWatchAddFunction( "Toggle Cameras Forwards", &ToggleCameraForwardsCallBack, this, player );
radDbgWatchAddFunction( "Toggle Cameras Backwards", &ToggleCameraBackwardsCallBack, this, player );
radDbgWatchAddFunction( "Toggle Burnout Test", &ToggleBurnoutCallBack, this, player );
radDbgWatchAddFunction( "Toggle Camera Cut", &ToggleCameraCut, this, player );
radDbgWatchAddFloat( &mDebugXZAngle, "Debug Camera XZ Angle", player, NULL, NULL, 0.0f, rmt::PI_2 );
radDbgWatchAddFloat( &mDebugYAngle, "Debug Camera Y Angle", player, NULL, NULL, 0.001f, rmt::PI_2 );
radDbgWatchAddFloat( &mDebugMagnitude, "Debug Camera Distance", player, NULL, NULL, 10.0f, 1000.0f );
radDbgWatchAddUnsignedInt( &mChanceToBurnout, "Burnout Cam Chance", player, NULL, NULL, 1, 100 );
radDbgWatchAddFloat( &mCameraCollisionFudge, "Camera Collision Fudge", player, NULL, NULL, 0.01f, 2.0f );
#endif
MEMTRACK_POP_GROUP( "SuperCamCentral" );
}
//=============================================================================
// SuperCamCentral::~SuperCamCentral
//=============================================================================
// Description: Destructor.
//
// Parameters: None.
//
// Return: N/A.
//
//=============================================================================
SuperCamCentral::~SuperCamCentral()
{
const bool shutdown = true;
Init( shutdown ); //Clear everything out.
#ifdef SUPERCAM_DEBUG
if ( mDebugCamera )
{
mDebugCamera->Release();
mDebugCamera = NULL;
}
if ( mFrustrumDrawable )
{
mFrustrumDrawable->Release();
mFrustrumDrawable = NULL;
}
#endif
if ( mCurrentFOVLocator )
{
mCurrentFOVLocator->Release();
mCurrentFOVLocator = NULL;
}
GetEventManager()->RemoveAll( this );
#ifdef DEBUGWATCH
radDbgWatchDelete( & ToggleDebugViewCallBack );
radDbgWatchDelete( & ToggleCameraForwardsCallBack );
radDbgWatchDelete( & ToggleCameraBackwardsCallBack );
radDbgWatchDelete( & mDebugXZAngle );
radDbgWatchDelete( & mDebugYAngle );
radDbgWatchDelete( & mDebugMagnitude );
radDbgWatchDelete( & mChanceToBurnout );
radDbgWatchDelete( & mCameraCollisionFudge );
#endif
}
//=============================================================================
// SuperCamCentral::Init
//=============================================================================
// Description: Comment
//
// Parameters: ( bool shutdown )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::Init( bool shutdown )
{
// Make sure this is a valid call
if( !shutdown && IsInit() || // already initialized
shutdown && !IsInit() ) // already shut down
{
return;
}
HeapMgr()->PushHeap( GMA_LEVEL_OTHER );
unsigned int i;
if ( mActiveSuperCam )
{
mActiveSuperCam->Shutdown();
}
for ( i = 0; i < MAX_CAMERAS; ++i )
{
if ( mSuperCameras[ i ] )
{
mSuperCameras[ i ]->UnregisterDebugControls();
mSuperCameras[ i ]->Release();
}
mSuperCameras[ i ] = NULL;
}
mActiveSuperCam = NULL;
mActiveSuperCamIndex = 0;
if ( mCurrentFOVLocator )
{
mCurrentFOVLocator->Release();
mCurrentFOVLocator = NULL;
}
if ( mCamera )
{
mCamera->Release();
}
mCamera = NULL;
mTarget = NULL;
#ifdef SUPERCAM_DEBUG
mDebugViewOn = false;
mDebugCamera->SetFOV( rmt::DegToRadian( DEBUG_CAM_FOV ), DEBUG_CAM_ASPECT );
mDebugCamera->SetNearPlane( DEBUG_CAM_NEAR );
mDebugCamera->SetFarPlane( DEBUG_CAM_FAR );
#endif
mIntersectionList.Clear();
if ( !shutdown )
{
// find mCollisionAreaIndex we can use:
mCollisionAreaIndex = GetWorldPhysicsManager()->GetCameraCollisionAreaIndex();
rAssert(mCollisionAreaIndex != -1);
// probably a good place to make the camera collision sphere
const rmt::Vector p(0.0f, 0.0f,0.0f);
const float sphereRadius = 2.0f; // TODO - what should this be.
mCameraCollisionVolume = new sim::SphereVolume(p, sphereRadius);
mCameraCollisionVolume->AddRef();
//mCameraCollisionObject = new(GMA_PERSISTENT)sim::CollisionObject(mCameraCollisionVolume);
//mCameraCollisionObject->AddRef();
mCameraSimState = (sim::ManualSimState*)sim::SimState::CreateManualSimState(mCameraCollisionVolume);
mCameraSimState->AddRef();
mCameraCollisionObject = mCameraSimState->GetCollisionObject();
mCameraCollisionObject->AddRef();
mCameraCollisionObject->SetManualUpdate(true);
mCameraCollisionObject->SetAutoPair(true);
mCameraCollisionObject->SetIsStatic(false); // hmmmmmm....
mCameraCollisionObject->SetCollisionEnabled(true);
char buffy[128];
sprintf(buffy, "camera_with_collision_area_index_%d", mCollisionAreaIndex);
mCameraCollisionObject->SetName(buffy);
mCameraSimState->mAIRefIndex = PhysicsAIRef::CameraSphere;
mCameraSimState->mAIRefPointer = (void*)this;
GetWorldPhysicsManager()->mCollisionManager->AddCollisionObject(mCameraCollisionObject, mCollisionAreaIndex);
mCameraCollisionCount = 0;
mCameraTerrainCollisionOffsetFix.Set(0.0f, 0.0f, 0.0f);
mController = new SuperCamController();
rAssert( mController );
mController->AddRef();
InputManager* im = InputManager::GetInstance();
rAssert( im );
int controllerID = GetInputManager()->GetControllerIDforPlayer( mMyNumber );
if( controllerID != -1 )
{
mControllerHandle = im->RegisterMappable( controllerID, mController );
if( mMyNumber == 0 )
{
const int NUM_CONTROLLERS = Input::MaxControllers;
// set secondary SuperCam controller to be = (primary + 1),
// and wrap back to controller 0
//
int secondaryControllerID = (controllerID + 1) % NUM_CONTROLLERS;
while ( !(GetInputManager()->GetController( secondaryControllerID )->IsConnected()) )
{
secondaryControllerID = (secondaryControllerID + 1) % NUM_CONTROLLERS;
if ( secondaryControllerID == controllerID )
{
secondaryControllerID = (secondaryControllerID + 1) % NUM_CONTROLLERS;
break;
}
}
SuperCam::SetSecondaryControllerID( static_cast<unsigned int>( secondaryControllerID ) );
}
}
if ( GetGameplayManager()->mIsDemo )
{
//GetEventManager()->AddListener( this, (EventEnum)(EVENT_LOCATOR + LocatorEvent::CAMERA_CUT) );
}
p3d::inventory->AddSection( CAMERA_INVENTORY_SECTION );
}
else
{
// remove from collision manager
// empty area?!
mCameraCollisionVolume->Release();
mCameraCollisionObject->Release();
GetWorldPhysicsManager()->FreeCollisionAreaIndex( mCollisionAreaIndex );
if ( mController )
{
InputManager* im = InputManager::GetInstance();
rAssert( im );
if( mControllerHandle != -1 )
{
int controllerID = GetInputManager()->GetControllerIDforPlayer( mMyNumber );
if ( controllerID == -1 )
{
im->UnregisterMappable( mController );
}
else
{
im->UnregisterMappable( controllerID, mControllerHandle );
}
}
mController->Release();
mController = NULL;
mControllerHandle = -1;
}
if ( mCameraSimState )
{
mCameraSimState->Release();
mCameraSimState = NULL;
}
p3d::inventory->RemoveSectionElements( tEntity::MakeUID( CAMERA_INVENTORY_SECTION ) );
p3d::inventory->DeleteSection( CAMERA_INVENTORY_SECTION );
}
//This is safe for startup or shutdown.
CleanupDataChunks();
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
}
//=============================================================================
// SuperCamCentral::IsInit
//=============================================================================
// Description: Returns true if cam initialized.
//
// Parameters: n/a
//
// Return: bool...
//
//=============================================================================
bool SuperCamCentral::IsInit() const
{
return mController != NULL;
}
//=============================================================================
// SuperCamCentral::UpdateCameraCollisionSpherePosition
//=============================================================================
// Description: Comment
//
// Parameters: (rmt::Vector& p)
//
// Return: void
//
//=============================================================================
void SuperCamCentral::UpdateCameraCollisionSpherePosition(rmt::Vector& p)
{
mCameraCollisionVolume->mPosition = p;
//mCameraCollisionObject->Update();
mCameraCollisionObject->PostManualUpdate();
}
//=============================================================================
// SuperCamCentral::UpdateCameraCollisionSphereRadius
//=============================================================================
// Description: Comment
//
// Parameters: (float radius)
//
// Return: void
//
//=============================================================================
void SuperCamCentral::UpdateCameraCollisionSphereRadius(float radius)
{
// this if for Cary
//
// not sure how he wants to use it.
mCameraCollisionVolume->UpdateRadius(radius);
}
//=============================================================================
// SuperCamCentral::Update
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int milliseconds, bool isFirstSubstep )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::Update( unsigned int milliseconds, bool isFirstSubstep )
{
#if defined(RAD_XBOX) || defined(RAD_WIN32)
if ( mController &&
!mCameraToggling &&
mController->GetValue( SuperCamController::cameraToggle ) == 1.0f &&
AllowCameraToggle() &&
GetGameplayManager()->GetGameType() != GameplayManager::GT_SUPERSPRINT &&
mActiveSuperCam &&
#ifdef RAD_WIN32
mActiveSuperCam->GetType() != SuperCam::PC_CAM &&
#endif
mActiveSuperCam->GetType() != SuperCam::WALKER_CAM )
{
ToggleSuperCam( true );
mCameraToggling = true;
}
else if ( mController && mCameraToggling && mController->GetValue( SuperCamController::cameraToggle) < 0.5f )
{
mCameraToggling = false;
}
#endif
//Test to see if we should change cameras or not.
if ( mNextSuperCam.incoming )
{
//Let's see if we should switch cameras.
if ( mNextSuperCam.nextCamDelay - static_cast<int>(milliseconds) <= 0 || mActiveSuperCam == NULL || mDoCameraCut )
{
if ( mDoCameraCut )
{
mNextSuperCam.timems = 0;
}
SetActiveSuperCam( mNextSuperCam.nextSuperCam, mNextSuperCam.flags, mNextSuperCam.timems );
}
else
{
mNextSuperCam.nextCamDelay -= milliseconds;
}
}
if ( mActiveSuperCam != NULL )
{
#ifdef PROFILER_ENABLED
char sCCname[256];
sprintf( sCCname, "SCC: %d Update", mMyNumber );
BEGIN_PROFILE( sCCname )
#endif
#if defined(DEBUGMENU) && defined(SUPERCAM_DEBUG)
if ( BEGIN_DEBUGINFO_SECTION("Super Cam Debug") )
{
DEBUGINFO_ADDLINE( rmt::Vector( 0,0,0 ), rmt::Vector(10.0f,0,0), tColour( 255, 0, 0 ) );
DEBUGINFO_ADDLINE( rmt::Vector( 0,0,0 ), rmt::Vector(0,10.0f,0), tColour( 0, 255, 0 ) );
DEBUGINFO_ADDLINE( rmt::Vector( 0,0,0 ), rmt::Vector(0,0,10.0f), tColour( 0, 0, 255 ) );
}
#endif
//Do the reverse cam thing if we're using the followcam
if ( ( mActiveSuperCam->GetType() == SuperCam::NEAR_FOLLOW_CAM ||
mActiveSuperCam->GetType() == SuperCam::FAR_FOLLOW_CAM ) &&
static_cast<FollowCam*>(mActiveSuperCam)->ShouldReverse() )
{
if ( !mNextSuperCam.incoming || mSuperCameras[mNextSuperCam.nextSuperCam]->GetType() != SuperCam::REVERSE_CAM )
{
SelectSuperCam( SuperCam::REVERSE_CAM, FORCE | NO_TRANS, 0 );
}
}
else if ( mActiveSuperCam->GetType() == SuperCam::REVERSE_CAM && mActiveSuperCam->CanSwitch() )
{
if ( !mNextSuperCam.incoming ||
( mSuperCameras[mNextSuperCam.nextSuperCam]->GetType() != SuperCam::NEAR_FOLLOW_CAM &&
mSuperCameras[mNextSuperCam.nextSuperCam]->GetType() != SuperCam::FAR_FOLLOW_CAM ) )
{
SelectSuperCam( SuperCam::FOLLOW_CAM, FORCE | NO_TRANS, 0 );
}
}
if ( mDoCameraCut )
{
mActiveSuperCam->DoCameraCut();
mDoCameraCut = false;
}
if ( mController )
{
//Test for lookback.
float lookBack = mController->GetValue( SuperCamController::lookBack );
#if defined(RAD_GAMECUBE) || defined(RAD_XBOX) //Both now!
float altLookBack = mController->GetValue( SuperCamController::altLookBack );
lookBack = mController->GetAxisValue( SuperCamController::stickY );
#if defined(RAD_XBOX)
lookBack = lookBack < -0.8f ? -1.0f : 0.0f;
#endif
if ( altLookBack == 1.0f || lookBack == -1.0f )
#elif defined(RAD_WIN32)
if( lookBack > 0.8f )
#else //This is PS2
if ( mController->GetValue( SuperCamController::l2) >= 0.9f && mController->GetValue( SuperCamController::r2 ) >= 0.9f )
{
lookBack = 1.0f;
}
if ( rmt::Fabs( lookBack ) > STICK_DEAD_ZONE )
#endif
{
//This will be reset at end of use.
mActiveSuperCam->LookBack( true );
}
}
#ifdef PROFILER_ENABLED
char sCname[256];
sprintf( sCname, "SC: %s #%d Update", mActiveSuperCam->GetName(), mMyNumber );
BEGIN_PROFILE( sCname )
#endif
if ( isFirstSubstep )
{
mIntersectionList.Clear();
rmt::Vector targetPos;
mTarget->GetPosition( &targetPos );
mIntersectionList.FillIntersectionListStatics( targetPos, mActiveSuperCam->GetIntersectionRadius() );
if ( mTarget->IsCar() )
{
Vehicle* playerCar = GetGameplayManager()->GetCurrentVehicle();
mIntersectionList.FillIntersectionListDynamics( targetPos, mActiveSuperCam->GetIntersectionRadius(), false, playerCar );
}
else
{
Character* playerCharacter = GetCharacterManager()->GetCharacter( 0 );
mIntersectionList.FillIntersectionListDynamics( targetPos, mActiveSuperCam->GetIntersectionRadius(), false, playerCharacter );
mIntersectionList.FillIntersectionListAnimPhys( targetPos, mActiveSuperCam->GetIntersectionRadius() );
}
}
//Update the currently active supercam.
#ifdef DEBUGWATCH
#ifdef PRINTCAMERANAMES
mActiveSuperCam->PrintClassName();
#endif
#endif
mActiveSuperCam->Update( milliseconds );
#ifdef PROFILER_ENABLED
END_PROFILE( sCname )
#endif
#if defined(DEBUGMENU) && defined(SUPERCAM_DEBUG)
//This displays the name of the active SuperCam
DEBUGINFO_ADDSCREENTEXTVECTOR( mActiveSuperCam->GetName(), DEBUG_NAME_POS )
END_DEBUGINFO_SECTION;
#endif
#ifdef PROFILER_ENABLED
END_PROFILE( sCCname )
#endif
//Hmmm Must think about this. This could be a virtual position and
//not really where the camera is.
rmt::Vector pos;
mActiveSuperCam->GetPosition(&pos);
if ( mActiveSuperCam->GetType() == SuperCam::WALKER_CAM ||
mActiveSuperCam->GetType() == SuperCam::FIRST_PERSON_CAM )
{
rmt::Vector heading;
mActiveSuperCam->GetHeading( &heading );
heading.NormalizeSafe();
heading.Scale( mActiveSuperCam->GetCollisionRadius() );
pos.Add( heading );
}
UpdateCameraCollisionSpherePosition(pos);
UpdateCameraCollisionSphereRadius( mActiveSuperCam->GetCollisionRadius() );
}
}
//=============================================================================
// SuperCamCentral::PreCollisionPrep
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperCamCentral::PreCollisionPrep()
{
mCameraCollisionCount = 0;
mCameraTerrainCollisionOffsetFix.Set(0.0f, 0.0f, 0.0f);
// new
// special vector just for ground collision
// do get intersects here.
bool foundTri = false;
bool foundPlane = false;
rmt::Vector closestTriNormal, closestTriPosn;
rmt::Vector planeNormal, planePosn;
rmt::Vector fudgedCollisionPos = mCameraCollisionVolume->mPosition;
// fudgedCollisionPos.y -= 1.0f; //Lower it down.
GetIntersectManager()->FindIntersection(fudgedCollisionPos,
foundPlane,
planeNormal,
planePosn );
// hmmm....
// if we get both a tri and a plane, use the one with the more upright normal?
// for starters, just use plane
if(foundPlane)
{
mCameraTerrainCollisionOffsetFix = planeNormal;
//mCameraTerrainCollisionOffsetFix.Set(0.0f, 1.0f, 0.0f);
rmt::Vector uptest(0.0f, 1.0f, 0.0f);
rAssert(planeNormal.DotProduct(uptest) > 0.0f);
float y = planePosn.y;
float penetratingDepth = y - (fudgedCollisionPos.y - mCameraCollisionVolume->mSphereRadius);
if(penetratingDepth > 0.0f)
{
float fixAlongPlaneNormal = penetratingDepth / rmt::Fabs( (planeNormal.DotProduct(uptest))); // the fabs should be redundant here
mCameraTerrainCollisionOffsetFix.Scale(fixAlongPlaneNormal);
}
else
{
mCameraTerrainCollisionOffsetFix.Set( 0.0f, 0.0f, 0.0f );
}
}
}
//=============================================================================
// SuperCamCentral::AddCameraCollisionOffset
//=============================================================================
// Description: Comment
//
// Parameters: (rmt::Vector& fixOffset)
//
// Return: void
//
//=============================================================================
void SuperCamCentral::AddCameraCollisionOffset(rmt::Vector& fixOffset)
{
rAssertMsg( mCameraCollisionCount < MAX_COLLISIONS, "Too many collisions for the camera! This one is ignored! \n" );
if ( mCameraCollisionCount >= MAX_COLLISIONS )
{
return;
}
if ( rmt::Epsilon( fixOffset.MagnitudeSqr(), 0.0000001f ) )
{
//Too small to care about.
return;
}
// if ( fixOffset.DotProduct( rmt::Vector( 0.0f, -1.0f, 0.0f ) ) > 0.0f )
// {
// //We don't get forced down.
// return;
// }
//Do we want to reject this collision?
rmt::Vector normalTestFix = fixOffset;
normalTestFix.NormalizeSafe();
unsigned int i;
for ( i = 0; i < mCameraCollisionCount; ++i )
{
const float dotTest = 0.7f;
float dotResult = normalTestFix.DotProduct( mCameraCollisionOffsetFix[ i ] );
if ( dotResult >= dotTest )
{
//Throw me away please.
return;
}
}
//Fuge-ma scale
fixOffset.Scale( 1.0f + mCameraCollisionFudge );
if ( mCameraCollisionCount < MAX_COLLISIONS )
{
mCameraCollisionOffsetFix[ mCameraCollisionCount ] = fixOffset;
mCameraCollisionCount++;
}
}
//=============================================================================
// SuperCamCentral::RegisterSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( SuperCam* cam )
//
// Return: unsigned int
//
//=============================================================================
unsigned int SuperCamCentral::RegisterSuperCam( SuperCam* cam )
{
rAssert( cam->GetType() < SuperCam::INVALID );
cam->AddRef();
cam->SetPlayerID( (int)mMyNumber );
unsigned int i;
bool added = false;
for ( i = 0; i < MAX_CAMERAS; ++i )
{
if ( mSuperCameras[ i ] == NULL )
{
mSuperCameras[ i ] = cam;
added = true;
break;
}
}
rAssert( added );
if ( mCamera )
{
cam->SetCamera( mCamera );
}
if ( mTarget )
{
cam->SetTarget( mTarget );
}
//DO this last in case the init needs to know about the cameras.
// cam->Init(); //Took out since it was call to often. Cary Jan 29
// increment number of registered super cams
mNumRegisteredSuperCams++;
cam->SetRegistered( true );
return i;
}
//=============================================================================
// SuperCamCentral::UnregisterSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( SuperCam* cam )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::UnregisterSuperCam( SuperCam* cam )
{
rAssert( cam != NULL );
if ( cam == NULL )
return;
rAssert( cam->GetType() < SuperCam::INVALID );
bool found = false;
unsigned int i;
for ( i = 0; i < MAX_CAMERAS; ++i )
{
if ( mSuperCameras[ i ] == cam )
{
mSuperCameras[ i ]->SetRegistered( false );
mSuperCameras[ i ]->UnregisterDebugControls();
mSuperCameras[ i ]->Release();
mSuperCameras[ i ] = NULL;
found = true;
break;
}
}
if ( !found )
{
return;
}
//If there is no incoming camera and the current cam is the active one, let's choose a new
//one intelligently.
if ( !mNextSuperCam.incoming && mActiveSuperCam == cam )
{
//This one is gone now.
mActiveSuperCam = NULL;
unsigned int timems = 7000;
int extraFlags = 0;
if ( mDoCameraCut )
{
timems = 0;
extraFlags = CUT;
}
//Should do something smart here. How about this...
SelectSuperCam( SuperCam::DEFAULT_CAM, FORCE | extraFlags, timems );
rAssert( mActiveSuperCam );
}
else if ( mNextSuperCam.incoming && mActiveSuperCam == cam )
{
SetActiveSuperCam( mNextSuperCam.nextSuperCam, mNextSuperCam.flags, mNextSuperCam.timems );
}
// decrement number of registered super cams
mNumRegisteredSuperCams--;
}
//=============================================================================
// SuperCamCentral::UnregisterSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int which )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::UnregisterSuperCam( unsigned int which )
{
rAssert( mSuperCameras[ which ] != NULL );
UnregisterSuperCam( mSuperCameras[ which ] );
}
//=============================================================================
// SuperCamCentral::GetNumRegisteredSuperCams
//=============================================================================
// Description: Comment
//
// Parameters: none
//
// Return: number of registered super cams
//
//=============================================================================
unsigned int SuperCamCentral::GetNumRegisteredSuperCams() const
{
return mNumRegisteredSuperCams;
}
//=============================================================================
// SuperCamCentral::GetActiveSuperCamIndex
//=============================================================================
// Description: Comment
//
// Parameters: none
//
// Return: index to active super cam
//
//=============================================================================
unsigned int SuperCamCentral::GetActiveSuperCamIndex() const
{
return mActiveSuperCamIndex;
}
//=============================================================================
// SuperCamCentral::GetSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: super cam index
//
// Return: reference to specified super cam
//
//=============================================================================
SuperCam* SuperCamCentral::GetSuperCam( unsigned int which ) const
{
rAssert( which < MAX_CAMERAS );
return mSuperCameras[ which ];
}
//=============================================================================
// SuperCamCentral::GetSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: super cam type
//
// Return: if found, return reference to super cam; otherwise, return NULL
//
//=============================================================================
SuperCam* SuperCamCentral::GetSuperCam( SuperCam::Type type ) const
{
SuperCam* superCam = NULL;
for( int i = 0; i < MAX_CAMERAS; i++ )
{
if( mSuperCameras[ i ] != NULL &&
mSuperCameras[ i ]->GetType() == type )
{
// found it!
//
superCam = mSuperCameras[ i ];
break;
}
}
return superCam;
}
//=============================================================================
// SuperCamCentral::ToggleSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( bool forwards, bool quickTransition )
//
// Return: bool
//
//=============================================================================
bool SuperCamCentral::ToggleSuperCam( bool forwards, bool quickTransition )
{
SuperCam::Type* cameras = NULL;
unsigned int numCameras = 0;
if ( mTarget->IsCar() )
{
if ( GetGameplayManager()->IsSuperSprint() )
{
cameras = SUPER_SPRINT_CAMERAS;
numCameras = NUM_SUPERSPRINT_CAMS;
}
else
{
cameras = CAMERAS_FOR_DRIVING;
if( GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_UNLOCK_CAMERAS ) )
{
numCameras = NUM_CAMERAS_FOR_DRIVING;
}
else
{
numCameras = NUM_CAMERAS_FOR_DRIVING_WITHOUT_CHEAT;
}
}
}
else
{
cameras = CAMERAS_FOR_WALKING;
if( GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_UNLOCK_CAMERAS ) )
{
numCameras = NUM_CAMERAS_FOR_WALKING;
}
else
{
numCameras = NUM_CAMERAS_FOR_WALKING_WITHOUT_CHEAT;
}
}
unsigned int start = 0;
unsigned int i;
for ( i = 0; i < numCameras; ++i )
{
if ( mActiveSuperCam && cameras[ i ] == mActiveSuperCam->GetType() )
{
start = i;
break;
}
}
unsigned int current;
if ( forwards )
{
current = (start+1) % numCameras;
}
else
{
current = ((start-1) + numCameras) % numCameras;
}
SelectSuperCam( cameras[ current ], SuperCamCentral::CUT | SuperCamCentral::QUICK, 0 );
return true;
}
//=============================================================================
// SuperCamCentral::SelectSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int which, int flags, unsigned int timems )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SelectSuperCam( unsigned int which, int flags, unsigned int timems )
{
if ( mNastyHypeCamHackEnabled )
{
//This is for the frickin' camera on level 6 where the user should never
//go, but can and will enevitably fuck the camera system.
return;
}
if ( which < MAX_CAMERAS && mSuperCameras[ which ] != NULL )
{
SuperCam::Type whichType = mSuperCameras[ which ]->GetType();
if ( !IsLegalType( whichType ) )
{
//This is a fix to trying to select cams you shouldn't (hack)
//You can't switch to a camera that isn't legal.
SelectSuperCam( SuperCam::DEFAULT_CAM, flags, timems );
return;
}
if( whichType == SuperCam::CONVERSATION_CAM )
{
ConversationCam* conv = dynamic_cast< ConversationCam* >( mSuperCameras[ which ] );
rAssert( conv != NULL );
conv->LockCharacterPositions();
}
else if ( whichType == SuperCam::BUMPER_CAM &&
mTarget->IsCar() )
{
//Always force.
flags |= FORCE;
//No bumper cam for RC Car.
Vehicle* target = dynamic_cast<Vehicle*>( mTarget );
rAssert( target );
if ( target->mVehicleID == VehicleEnum::DUNE_V )
{
SelectSuperCam( SuperCam::NEAR_FOLLOW_CAM, flags, timems );
return;
}
}
SuperCam::Type activeType;
if( mActiveSuperCam != NULL )
{
activeType = mActiveSuperCam->GetType();
}
if ( mActiveSuperCam == NULL || timems == 0 )
{
SetActiveSuperCam( which, flags, timems );
}
else if(
( mSuperCameras[ which ]->GetType() == SuperCam::ANIMATED_CAM ) ||
( mSuperCameras[ which ]->GetType() == SuperCam::RELATIVE_ANIMATED_CAM )
)
{
AnimatedCam* cam = static_cast< AnimatedCam* >( mSuperCameras[ which ] );
SuperCam::Type currentType = mSuperCameras[ mActiveSuperCamIndex ]->GetType();
cam->SetNextCameraType( currentType );
SetActiveSuperCam( which, flags, timems );
}
else if( mActiveSuperCam && ( activeType == SuperCam::ANIMATED_CAM ) && ( ( flags & FORCE ) == 0x00 ) )
{
AnimatedCam* cam = dynamic_cast< AnimatedCam* >( GetSuperCam( SuperCam::ANIMATED_CAM ) );
rAssert( cam != NULL );
cam->SetNextCameraType( mSuperCameras[ which ]->GetType() );
}
else
{
//Crap.. Let's eliminate this...
/*
mNextSuperCam.nextSuperCam = which;
if ( timems == 0 )
{
mNextSuperCam.nextCamDelay = 0;
}
else
{
mNextSuperCam.nextCamDelay = DEFAULT_CAM_SWITCH_DELAY;
}
mNextSuperCam.flags = flags;
mNextSuperCam.timems = timems;
mNextSuperCam.incoming = true;
*/
SetActiveSuperCam( which, flags, timems );
}
}
}
//=============================================================================
// SuperCamCentral::SelectSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( SuperCam::Type type, int flags, unsigned int timems )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SelectSuperCam( SuperCam::Type type, int flags, unsigned int timems )
{
if ( type == SuperCam::DEFAULT_CAM )
{
if( mTarget == NULL )
{
type = SuperCam::FOLLOW_CAM;
}
else if ( mTarget->IsCar() )
{
if ( GetGameplayManager()->mIsDemo )
{
type = SuperCam::FOLLOW_CAM;
}
else if ( GetGameplayManager()->IsSuperSprint() )
{
type = SuperCam::SUPER_SPRINT_CAM;
}
else
{
type = SuperCam::FOLLOW_CAM;
}
}
else
{
#ifdef RAD_WIN32
type = SuperCam::ON_FOOT_CAM;
#else
type = SuperCam::WALKER_CAM;
#endif
}
}
#ifdef RAD_WIN32
if ( type == SuperCam::ON_FOOT_CAM )
{
//Ziemek? Check the PC cam flag here.
bool bMouseLookMode = GetInputManager()->GetController(0)->IsMouseLookOn();
if ( bMouseLookMode ) //Or PC flag is set
{
type = SuperCam::PC_CAM;
}
else
{
type = SuperCam::WALKER_CAM;
}
}
#endif
if ( type == SuperCam::FOLLOW_CAM )
{
//Find the preferred type
type = mPreferredFollowCam;
}
else if ( type == SuperCam::NEAR_FOLLOW_CAM || type == SuperCam::FAR_FOLLOW_CAM || type == SuperCam::BUMPER_CAM || type == SuperCam::COMEDY_CAM )
{
//Set the new preferred type
mPreferredFollowCam = type;
}
//If it still ain't legal, make it legal.
if ( !IsLegalType( type ) )
{
type = SuperCam::FAR_FOLLOW_CAM;
mPreferredFollowCam = type;
}
unsigned int i;
for ( i = 0; i < MAX_CAMERAS; ++i )
{
if ( mSuperCameras[ i ] != NULL )
{
if ( mSuperCameras[ i ]->GetType() == type )
{
SelectSuperCam( i, flags, timems );
break;
}
}
}
}
//=============================================================================
// SuperCamCentral::SelectSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( SuperCam* cam, int flags = CUT | QUICK, unsigned int timems = 7000 )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SelectSuperCam( SuperCam* cam, int flags, unsigned int timems )
{
rAssert( cam );
if ( cam )
{
unsigned int i;
for ( i = 0; i < MAX_CAMERAS; ++i )
{
if ( mSuperCameras[ i ] != NULL )
{
if ( mSuperCameras[ i ] == cam )
{
SelectSuperCam( i, flags, timems );
break;
}
}
}
}
}
//=============================================================================
// SuperCamCentral::SetCamera
//=============================================================================
// Description: Comment
//
// Parameters: ( tPointCamera* cam )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SetCamera( tPointCamera* cam )
{
if ( mCamera )
{
mCamera->Release();
}
unsigned int i;
for ( i = 0; i < MAX_CAMERAS; ++i )
{
if ( mSuperCameras[ i ] )
{
mSuperCameras[ i ]->SetCamera( cam );
}
}
mCamera = cam;
cam->AddRef();
}
//=============================================================================
// SuperCamCentral::SetTarget
//=============================================================================
// Description: Comment
//
// Parameters: ( ISuperCamTarget* target )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SetTarget( ISuperCamTarget* target )
{
if ( mTarget != target )
{
unsigned int i;
for ( i = 0; i < MAX_CAMERAS; ++i )
{
if ( mSuperCameras[ i ] )
{
mSuperCameras[ i ]->SetTarget( target );
}
}
//We should do a transition on the active super cam to make sure that
//We don't jump around too much.
if ( mActiveSuperCam )
{
mActiveSuperCam->DoCameraTransition( false );
}
mTarget = target;
}
}
//=============================================================================
// SuperCamCentral::AddTarget
//=============================================================================
// Description: Comment
//
// Parameters: ( ISuperCamTarget* target )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::AddTarget( ISuperCamTarget* target )
{
mActiveSuperCam->AddTarget( target );
if ( mNextSuperCam.incoming )
{
rAssert( mNextSuperCam.nextSuperCam < MAX_CAMERAS );
rAssert( mSuperCameras[ mNextSuperCam.nextSuperCam ] != NULL );
mSuperCameras[ mNextSuperCam.nextSuperCam ]->AddTarget( target );
}
}
//=============================================================================
// SuperCamCentral::SetActiveSuperCam
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int which, int flags, unsigned int timems )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SetActiveSuperCam( unsigned int which, int flags, unsigned int timems )
{
//Clear the incoming.
mNextSuperCam.incoming = false;
if ( !AllowCameraToggle() && (flags & FORCE) == 0 ) //Not forced
{
return;
}
if ( mSuperCameras[ which ] == mActiveSuperCam )
{
//This one is already active.
if( ( mNextSuperCam.flags & FORCE ) != 0 )
{
mActiveSuperCam->EndTransition();
}
if ( (flags & CUT) != 0 )
{
mActiveSuperCam->DoCameraCut();
}
return;
}
bool oldWasBumperCam = false;
if ( mActiveSuperCam != NULL )
{
mActiveSuperCam->UnregisterDebugControls();
mActiveSuperCam->Shutdown();
oldWasBumperCam = mActiveSuperCam->GetType() == SuperCam::BUMPER_CAM;
}
if ( mSuperCameras[ which ] != NULL)
{
mActiveSuperCam = mSuperCameras[ which ];
mActiveSuperCam->RegisterDebugControls();
GetEventManager()->TriggerEvent( EVENT_CAMERA_CHANGE, mActiveSuperCam );
mActiveSuperCamIndex = which;
//Hack.. TODO: Should this be moved?
mActiveSuperCam->SetNearPlane( SUPERCAM_NEAR );
mActiveSuperCam->Init();
mActiveSuperCam->ResetTwistDelta(); //This stops funny twist snap
if ( mCurrentFOVLocator )
{
//Enable the FOV override here. There could be some issues with timing, but we'll see.
mActiveSuperCam->SetFOVOverride( mCurrentFOVLocator->GetFOV() );
mActiveSuperCam->OverrideFOV( true, mCurrentFOVLocator->GetTime(), mCurrentFOVLocator->GetRate() );
}
//Cut the camera view
if ( (flags & CUT) != 0 ||
oldWasBumperCam ||
mActiveSuperCam->GetType() == SuperCam::BUMPER_CAM ) //Auto cut on bumper cam too
{
mActiveSuperCam->DoCameraCut();
}
else if ( (flags & NO_TRANS) == 0 )
{
//Smothly blend the camera views
mActiveSuperCam->DoCameraTransition( (flags & QUICK) != 0, timems );
}
mActiveSuperCam->DoFirstTime();
rDebugString( "NEW SUPER CAM!\n" );
}
}
//=============================================================================
// SuperCamCentral::SubmitStatics
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SubmitStatics()
{
// only do this for certain types of camers:
// TODO - add others?
SuperCam::Type camType = mActiveSuperCam->GetType();
rmt::Vector pos;
pos = mCameraCollisionVolume->mPosition;
if( mActiveSuperCam &&
(camType == SuperCam::NEAR_FOLLOW_CAM ||
camType == SuperCam::FAR_FOLLOW_CAM ||
camType == SuperCam::WALKER_CAM ||
#ifdef RAD_WIN32
camType == SuperCam::PC_CAM ||
#endif
camType == SuperCam::COMEDY_CAM ||
camType == SuperCam::FIRST_PERSON_CAM ||
camType == SuperCam::REVERSE_CAM)
)
{
GetWorldPhysicsManager()->SubmitStaticsPseudoCallback(pos, mActiveSuperCam->GetCollisionRadius() /* need multiplier? */, mCollisionAreaIndex, mCameraSimState);
GetWorldPhysicsManager()->SubmitFencePiecesPseudoCallback(pos, mActiveSuperCam->GetCollisionRadius(),
mCollisionAreaIndex, mCameraSimState);
GetWorldPhysicsManager()->SubmitAnimCollisionsPseudoCallback( pos, mActiveSuperCam->GetCollisionRadius(), mCollisionAreaIndex, mCameraSimState );
#ifdef RAD_WIN32
if ( camType == SuperCam::PC_CAM )
{
//No dynamics in PC_CAM
return;
}
#endif
GetWorldPhysicsManager()->SubmitDynamicsPseudoCallback( pos, mActiveSuperCam->GetCollisionRadius(), mCollisionAreaIndex, mCameraSimState );
}
}
//=============================================================================
// SuperCamCentral::UpdateForPhysics
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int milliseconds )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::UpdateForPhysics( unsigned int milliseconds )
{
if ( mActiveSuperCam )
{
//Inform the supercam of the physics collision
// hi Cary
// at this point you should now also have a
// rmt::Vector mCameraTerrainCollisionOffsetFix
// that will be something other than 0,0,0 if the camera sphere hit the terrain
//
// use as you please.
mActiveSuperCam->SetCollisionOffset( mCameraCollisionOffsetFix, mCameraCollisionCount, mCameraTerrainCollisionOffsetFix );
mActiveSuperCam->UpdateForPhysics( milliseconds );
#ifdef SUPERCAM_DEBUG
//This is the debug system to allow the game to "see" what the active supercam sees.
if ( mDebugViewOn )
{
//Position the debug cam relative to the actual cam
rmt::Vector newPos, camPos;
mCamera->GetPosition( &camPos );
rmt::SphericalToCartesian( mDebugMagnitude, mDebugXZAngle, mDebugYAngle,
&newPos.x, &newPos.z, &newPos.y );
newPos.Add( camPos );
mDebugCamera->SetPosition( newPos );
mDebugCamera->SetTarget( camPos );
#ifdef DEBUGWATCH
//Draw the cam's frustrum.
DrawFrustrum( );
#endif
}
#endif
}
}
//=============================================================================
// SuperCamCentral::AllowCameraToggle
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: bool
//
//=============================================================================
bool SuperCamCentral::AllowCameraToggle()
{
if ( mActiveSuperCam == NULL )
{
return true;
}
//In these modes do not allow the camera to be toggled.
SuperCam::Type type = mActiveSuperCam->GetType();
return !( type == SuperCam::RAIL_CAM || type == SuperCam::STATIC_CAM || type == SuperCam::ANIMATED_CAM );
}
//=============================================================================
// SuperCamCentral::AllowAutoCameraChange
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: bool
//
//=============================================================================
bool SuperCamCentral::AllowAutoCameraChange()
{
if ( mActiveSuperCam == NULL )
{
return true;
}
SuperCam::Type type = mActiveSuperCam->GetType();
return ( type == SuperCam::FOLLOW_CAM ||
type == SuperCam::NEAR_FOLLOW_CAM ||
type == SuperCam::FAR_FOLLOW_CAM ||
type == SuperCam::WALKER_CAM ||
#ifdef RAD_WIN32
type == SuperCam::PC_CAM ||
#endif
type == SuperCam::COMEDY_CAM ||
type == SuperCam::BUMPER_CAM ||
type == SuperCam::RAIL_CAM ||
type == SuperCam::STATIC_CAM ||
type == SuperCam::SPLINE_CAM );
}
//=============================================================================
// SuperCamCentral::RegisterFOVLocator
//=============================================================================
// Description: Comment
//
// Parameters: ( FOVLocator* loc )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::RegisterFOVLocator( FOVLocator* loc )
{
rAssertMsg( NULL == mCurrentFOVLocator, "There should never be FOV locators that interpenetrate!" );
mCurrentFOVLocator = loc;
mCurrentFOVLocator->AddRef();
if ( mActiveSuperCam )
{
mActiveSuperCam->SetFOVOverride( loc->GetFOV() );
mActiveSuperCam->OverrideFOV( true, loc->GetTime(), loc->GetRate() );
}
}
//=============================================================================
// SuperCamCentral::UnregisterFOVLocator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperCamCentral::UnregisterFOVLocator()
{
rAssert( mCurrentFOVLocator );
if ( mActiveSuperCam )
{
mActiveSuperCam->OverrideFOV( false, mCurrentFOVLocator->GetTime(), mCurrentFOVLocator->GetRate() );
}
mCurrentFOVLocator->Release();
mCurrentFOVLocator = NULL;
}
//=============================================================================
// SuperCamCentral::NoTransition
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperCamCentral::NoTransition()
{
if ( mNextSuperCam.incoming )
{
mNextSuperCam.flags |= FORCE;
}
else
{
if( mActiveSuperCam != NULL )
{
mActiveSuperCam->EndTransition();
}
}
}
//=============================================================================
// SuperCamCentral::HandleEvent
//=============================================================================
// Description: Comment
//
// Parameters: ( EventEnum id, void* pEventData )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::HandleEvent( EventEnum id, void* pEventData )
{
switch ( id )
{
case EVENT_ENTER_INTERIOR_END:
{
DoCameraCut();
break;
}
case EVENT_CAMERA_SHAKE:
{
ShakeEventData* shakeData = static_cast<ShakeEventData*>(pEventData);
if ( shakeData->playerID == mMyNumber && GetGameplayManager()->GetGameType() == GameplayManager::GT_NORMAL )
{
//Do the shaking.
mActiveSuperCam->EnableShake();
mActiveSuperCam->SetCameraShakerData( shakeData );
}
break;
}
case EVENT_LOCATOR + LocatorEvent::CAMERA_CUT:
{
EventLocator* evtLoc = static_cast<EventLocator*>(pEventData);
if ( evtLoc->GetPlayerID() == mMyNumber )
{
//Only switch to Wreckless cam in demo mode.
if ( GetGameplayManager()->mIsDemo )
{
if ( evtLoc->GetPlayerEntered() )
{
SelectSuperCam( SuperCam::WRECKLESS_CAM, CUT | FORCE, 0 ); //0 means do right away.
//Hackish, trigger the cameras event listener. This is specific to wreckless cams.
WrecklessCam* wc = static_cast<WrecklessCam*>(GetSuperCam( SuperCam::WRECKLESS_CAM ));
if ( wc )
{
wc->GetEventListener()->HandleEvent( id, pEventData );
}
++mWrecklessCount;
}
else
{
if ( mWrecklessCount == 1 )
{
if ( mTarget->IsCar() )
{
SelectSuperCam( SuperCam::FOLLOW_CAM, CUT | FORCE );
}
else
{
#ifdef RAD_WIN32
SelectSuperCam( SuperCam::ON_FOOT_CAM, CUT | FORCE );
#else
SelectSuperCam( SuperCam::WALKER_CAM, CUT | FORCE );
#endif
}
}
mWrecklessCount--;
}
}
}
break;
}
default:
{
break;
}
}
/* else if ( id == EVENT_BURNOUT )
{
if ( rand() % mChanceToBurnout == 0 )
{
SelectSuperCam( SuperCam::BURNOUT_CAM, true, false, true );
}
}
else if ( id == EVENT_BURNOUT_END )
{
SelectSuperCam( SuperCam::FOLLOW_CAM, false, false, true );
}
*/
}
//=============================================================================
// SuperCamCentral::ToggleFirstPerson
//=============================================================================
// Description: Comment
//
// Parameters: ( int controllerID )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::ToggleFirstPerson( int controllerID )
{
/*
if ( controllerID == GetInputManager()->GetControllerIDforPlayer( mMyNumber ) )
{
if ( mActiveSuperCam && mActiveSuperCam->GetType() == SuperCam::WALKER_CAM )
{
//Switch to first person cam.
SelectSuperCam( SuperCam::FIRST_PERSON_CAM, SuperCamCentral::CUT | SuperCamCentral::FORCE, 0 );
GetEventManager()->TriggerEvent(EVENT_TOGGLE_FIRSTPERSON, (void*)true);
}
else if ( mActiveSuperCam && mActiveSuperCam->GetType() == SuperCam::FIRST_PERSON_CAM )
{
//Switch to walker cam
SelectSuperCam( SuperCam::WALKER_CAM, SuperCamCentral::CUT | SuperCamCentral::FORCE, 0 );
GetEventManager()->TriggerEvent(EVENT_TOGGLE_FIRSTPERSON, (void*)false);
}
}
*/
}
//=============================================================================
// SuperCamCentral::IsCutCam
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: bool
//
//=============================================================================
bool SuperCamCentral::IsCutCam()
{
return !( mActiveSuperCam != NULL &&
mActiveSuperCam->GetType() != SuperCam::STATIC_CAM &&
mActiveSuperCam->GetType() != SuperCam::RAIL_CAM );
}
//*****************************************************************************
// Debug Stuff
//*****************************************************************************
//=============================================================================
// SuperCamCentral::ToggleDebugView
//=============================================================================
// Description: Comment
//
// Parameters: ( bool on )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::ToggleDebugView( bool on )
{
#ifdef SUPERCAM_DEBUG
rAssert( mCamera );
RenderManager* rm = GetRenderManager();
RenderLayer* rloutside = rm->mpLayer( RenderEnums::LevelSlot );
rAssert( rloutside );
// TO DO: Cary, this isn't good... do we care which player?
tView* viewOutside = rloutside->pView( 0 );
if ( on && !mDebugViewOn )
{
//Turn on
viewOutside->SetCamera( mDebugCamera );
rloutside->AddGuts( mFrustrumDrawable );
mFrustrumDrawable->Enable();
mDebugXZAngle = DEBUG_CAM_XZ_ANGLE;
mDebugYAngle = DEBUG_CAM_Y_ANGLE;
mDebugMagnitude = DEBUG_CAM_DIST;
}
else if ( !on && mDebugViewOn )
{
//Turn off
viewOutside->SetCamera( mCamera );
rloutside->RemoveGuts( mFrustrumDrawable );
mFrustrumDrawable->Disable();
}
mDebugViewOn = on;
#endif
}
//=============================================================================
// SuperCamCentral::ToggleDebugView
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperCamCentral::ToggleDebugView()
{
#ifdef SUPERCAM_DEBUG
ToggleDebugView( !mDebugViewOn );
#endif
}
#ifdef DEBUGWATCH
//=============================================================================
// SuperCamCentral::DrawFrustrum
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperCamCentral::DrawFrustrum()
{
rmt::Vector wnp[4], wfp[4];
rmt::Vector temp;
rmt::Vector realPos;
const tColour colour( tColour( 255, 255, 255 ) );
mCamera->GetPosition( &realPos );
float tempFP = mCamera->GetFarPlane();
mCamera->SetFarPlane(200.0f);
mCamera->ViewToWorld( rmt::Vector( -0.5f, 0.5f, 0 ), &wnp[0], &wfp[0] );
mCamera->ViewToWorld( rmt::Vector( 0.5f, 0.5f, 0 ), &wnp[1], &wfp[1] );
mCamera->ViewToWorld( rmt::Vector( 0.5f, -0.5f, 0 ), &wnp[2], &wfp[2] );
mCamera->ViewToWorld( rmt::Vector( -0.5f, -0.5f, 0 ), &wnp[3], &wfp[3] );
mCamera->SetFarPlane(tempFP);
//This is hard coded line drawing.
mFrustrumDrawable->SetColour( colour );
mFrustrumDrawable->SetPoints( mCameraCollisionVolume->mPosition, realPos, wfp[0], wfp[1], wfp[2], wfp[3] );
mFrustrumDrawable->SetScale( mActiveSuperCam->GetCollisionRadius() );
mFrustrumDrawable->SetSuperCam( mActiveSuperCam );
}
#endif
//=============================================================================
// SuperCamCentral::LoadData
//=============================================================================
// Description: Comment
//
// Parameters: ( const GameDataByte* dataBuffer, unsigned int numBytes )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::LoadData( const GameDataByte* dataBuffer, unsigned int numBytes )
{
GameDataByte bitmask = dataBuffer[ 0 ];
/*
* BITS: 7654 3210
*
* bitmask = [ **** ***? ] = jump cameras on/off flag
* bitmask = [ **** **?* ] = inverted camera on/off flag
* bitmask = [ ???? ??** ] = preferred follow camera type
*
*/
mJumpCamsEnabled = ( (bitmask & 0x01) > 0 );
mIsInvertedCameraEnabled = ( (bitmask & 0x02) > 0 );
GameDataByte preferredFollowCam = (bitmask >> 2);
if( preferredFollowCam == 0 )
{
// this is for backward-compatibility w/ old saved game formats
// that didn't have the preferred follow cam data
//
mPreferredFollowCam = SuperCam::FAR_FOLLOW_CAM;
}
else
{
mPreferredFollowCam = static_cast<SuperCam::Type>( preferredFollowCam );
}
}
//=============================================================================
// SuperCamCentral::SaveData
//=============================================================================
// Description: Comment
//
// Parameters: ( GameDataByte* dataBuffer, unsigned int numBytes )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::SaveData( GameDataByte* dataBuffer, unsigned int numBytes )
{
GameDataByte bitmask = 0x00;
/*
* BITS: 7654 3210
*
* bitmask = [ **** ***? ] = jump cameras on/off flag
* bitmask = [ **** **?* ] = inverted camera on/off flag
* bitmask = [ ???? ??** ] = preferred follow camera type
*
*/
if( mJumpCamsEnabled )
{
bitmask |= 0x01;
}
if( mIsInvertedCameraEnabled )
{
bitmask |= 0x02;
}
GameDataByte preferredFollowCam = static_cast<GameDataByte>( mPreferredFollowCam );
rAssertMsg( (preferredFollowCam & 0xC0) == 0,
"Not enough bits to save preferred follow cam data!" );
bitmask |= (preferredFollowCam << 2);
dataBuffer[ 0 ] = bitmask;
}
//=============================================================================
// SuperCamCentral::ResetData
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperCamCentral::ResetData()
{
mJumpCamsEnabled = true;
mIsInvertedCameraEnabled = false;
mPreferredFollowCam = FollowCam::FAR_FOLLOW_CAM;
}
//=============================================================================
// SuperCamCentral::IsLegalType
//=============================================================================
// Description: Comment
//
// Parameters: ( SuperCam::Type type )
//
// Return: bool
//
//=============================================================================
bool SuperCamCentral::IsLegalType( SuperCam::Type type )
{
if( mTarget == NULL )
{
return false;
}
if ( type == SuperCam::STATIC_CAM ||
type == SuperCam::RAIL_CAM ||
type == SuperCam::CONVERSATION_CAM ||
(mTarget != NULL && !mTarget->IsCar() && type == SuperCam::FIRST_PERSON_CAM ) ||
(mTarget != NULL && mTarget->IsCar() && type == SuperCam::REVERSE_CAM) ||
type == SuperCam::ANIMATED_CAM ||
type == SuperCam::RELATIVE_ANIMATED_CAM ||
type == SuperCam::SUPER_SPRINT_CAM )
{
return true;
}
SuperCam::Type* cameras = NULL;
unsigned int numCameras = 0;
if( mTarget != NULL && mTarget->IsCar() )
{
if ( GetGameplayManager()->IsSuperSprint() )
{
cameras = SUPER_SPRINT_CAMERAS;
numCameras = NUM_SUPERSPRINT_CAMS;
}
else
{
cameras = CAMERAS_FOR_DRIVING;
if( GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_UNLOCK_CAMERAS ) )
{
numCameras = NUM_CAMERAS_FOR_DRIVING;
}
else
{
numCameras = NUM_CAMERAS_FOR_DRIVING_WITHOUT_CHEAT;
}
}
}
else
{
cameras = CAMERAS_FOR_WALKING;
if( GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_UNLOCK_CAMERAS ) )
{
numCameras = NUM_CAMERAS_FOR_WALKING;
}
else
{
numCameras = NUM_CAMERAS_FOR_WALKING_WITHOUT_CHEAT;
}
}
unsigned int i;
for ( i = 0; i < numCameras; ++i )
{
if ( cameras[ i ] == type )
{
return true;
}
}
return false;
}
//=============================================================================
// SuperCamCentral::GetNewFollowCamDataChunk
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: FollowCamDataChunk
//
//=============================================================================
FollowCamDataChunk& SuperCamCentral::GetNewFollowCamDataChunk()
{
rAssert( mNumUsedFDC < MAX_DATA_CHUNKS );
if ( mNumUsedFDC < MAX_DATA_CHUNKS )
{
FollowCamDataChunk& chunk = mFollowCamDataChunks[ mNumUsedFDC ];
++mNumUsedFDC;
return chunk;
}
return mFollowCamDataChunks[ 0 ]; //This is BAD, but not fatal
}
//=============================================================================
// SuperCamCentral::ReleaseFollowCamDataChunk
//=============================================================================
// Description: Comment
//
// Parameters: ( FollowCamDataChunk& chunk )
//
// Return: void
//
//=============================================================================
void SuperCamCentral::ReleaseFollowCamDataChunk( FollowCamDataChunk& chunk )
{
unsigned int i;
for ( i = 0; i < mNumUsedFDC; ++i )
{
if ( mFollowCamDataChunks[ i ] == chunk )
{
mFollowCamDataChunks[ i ] = mFollowCamDataChunks[ mNumUsedFDC - 1 ];
mNumUsedFDC--;
return;
}
}
}
//=============================================================================
// SuperCamCentral::FindFCD
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int id )
//
// Return: FollowCamDataChunk*
//
//=============================================================================
FollowCamDataChunk* SuperCamCentral::FindFCD( unsigned int id )
{
unsigned int i;
for ( i = 0; i < mNumUsedFDC; ++i )
{
if ( mFollowCamDataChunks[ i ].mID == id )
{
return &mFollowCamDataChunks[ i ];
}
}
return NULL;
}
//*****************************************************************************
//
// Private Member Functions
//
//*****************************************************************************