//============================================================================= // Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. // // File: triggervolumetracker.cpp // // Description: Implement TriggerVolumeTracker // // History: 13/05/2002 + Created -- NAME // //============================================================================= //======================================== // System Includes //======================================== // Foundation Tech #include #include #include #include #include //======================================== // Project Includes //======================================== #include #include #include #include #include #include #include #include
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LocatorEvent::Event ALLOWED_AI_EVENTS[] = { LocatorEvent::DEATH, LocatorEvent::PARKED_BIRDS, LocatorEvent::WHACKY_GRAVITY, LocatorEvent::GOO_DAMAGE }; unsigned int NUM_ALLOWED_AI_EVENTS = sizeof( ALLOWED_AI_EVENTS ) / sizeof( ALLOWED_AI_EVENTS[0] ); //****************************************************************************** // // Global Data, Local Data, Local Classes // //****************************************************************************** // Static pointer to instance of singleton. TriggerVolumeTracker* TriggerVolumeTracker::spInstance = NULL; rmt::Vector TriggerVolumeTracker::sP1; rmt::Vector TriggerVolumeTracker::sP2; rmt::Vector TriggerVolumeTracker::sP3; rmt::Vector TriggerVolumeTracker::sP4; sim::CollisionVolumeTypeEnum TriggerVolumeTracker::sColType; //****************************************************************************** // // Public Member Functions // //****************************************************************************** void TriggerVolumeTracker::CreateInstance() { MEMTRACK_PUSH_GROUP( "TriggerVolumeTracker" ); rAssert( spInstance == NULL ); spInstance = new(GMA_PERSISTENT) TriggerVolumeTracker(); rAssert( spInstance ); MEMTRACK_POP_GROUP( "TriggerVolumeTracker" ); } //============================================================================= // TriggerVolumeTracker::GetInstance //============================================================================= // Description: Comment // // Parameters: () // // Return: TriggerVolumeTracker // //============================================================================= TriggerVolumeTracker* TriggerVolumeTracker::GetInstance() { //rAssert( spInstance ); return spInstance; } //============================================================================= // TriggerVolumeTracker::DestroyInstance //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void TriggerVolumeTracker::DestroyInstance() { if( spInstance != NULL ) { delete( GMA_PERSISTENT, spInstance ); spInstance = NULL; } } //============================================================================== // TriggerVolumeTracker::TriggerVolumeTracker //============================================================================== // Description: Constructor. // // Parameters: None. // // Return: N/A. // //============================================================================== TriggerVolumeTracker::TriggerVolumeTracker() : mpTriggerSphere( NULL ), mNumRegisteredAI( 0 ), mIgnoreTriggers ( false ) #ifndef RAD_RELEASE , mDisplayAmbients( false ), mDisplayActive( true ), mDisplayInactive( false ), mDisplayAll( false ) #endif { int i; for( i = 0; i < MAX_PLAYERS; i++ ) { mActiveCount[ i ] = 0; } for ( i = 0; i < MAX_AI; ++i ) { mAICount[ i ] = 0; } mTriggerCount = 0; #ifndef RAD_RELEASE radDbgWatchAddBoolean( &mDisplayActive, "Display Active Vols" , "Trigger Volume Tracker" ); radDbgWatchAddBoolean( &mDisplayInactive, "Display Inactive Vols" , "Trigger Volume Tracker" ); radDbgWatchAddBoolean( &mDisplayAll, "Display ALL" , "Trigger Volume Tracker" ); for ( i = 0; i < LocatorType::NUM_TYPES; ++i ) { char name[256]; sprintf( name, "Display %s", LocatorType::Name[i] ); radDbgWatchAddBoolean( &mDisplayEnable[i], name , "Trigger Volume Tracker" ); mDisplayEnable[i] = false; } radDbgWatchAddBoolean( &mDisplayAmbients, "Display Ambients", "Trigger Volume Tracker" ); material = NULL; #endif } #ifndef RAD_RELEASE pddiShader* TriggerVolumeTracker::GetMaterial(void) { if(!material) { HeapMgr()->PushHeap(GMA_PERSISTENT); material = p3d::device->NewShader( "simple" ); material->AddRef(); material->SetInt( PDDI_SP_BLENDMODE, PDDI_BLEND_ADD); material->SetColour( PDDI_SP_AMBIENT, pddiColour( 128, 128, 128, 64 )); material->SetColour( PDDI_SP_DIFFUSE, pddiColour( 128, 128, 128, 64 )); HeapMgr()->PopHeap(GMA_PERSISTENT); } return material; } #endif //============================================================================== // TriggerVolumeTracker::~TriggerVolumeTracker //============================================================================== // Description: Destructor. // // Parameters: None. // // Return: N/A. // //============================================================================== TriggerVolumeTracker::~TriggerVolumeTracker() { Cleanup(); #ifndef RAD_RELEASE radDbgWatchDelete( &mDisplayActive ); radDbgWatchDelete( &mDisplayInactive ); radDbgWatchDelete( &mDisplayAll ); int i; for ( i = 0; i < LocatorType::NUM_TYPES; ++i ) { radDbgWatchDelete( &mDisplayEnable[i] ); } radDbgWatchDelete( &mDisplayAmbients ); if ( material ) { material->Release(); } #endif } //============================================================================= // TriggerVolumeTracker::Cleanup //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void TriggerVolumeTracker::Cleanup() { unsigned int i; int j; for( j = 0; j < MAX_PLAYERS; j++ ) { for( i = 0; i < mActiveCount[ j ]; i++ ) { mActiveVolumes[ j ][ i ]->Release(); mActiveVolumes[ j ][ i ] = NULL; } mActiveCount[ j ] = 0; } for ( j = 0; j < MAX_AI; ++j ) { for ( i = 0; i < mAICount[ j ]; ++i ) { mActiveAIVolumes[ j ][ i ]->Release(); mActiveAIVolumes[ j ][ i ] = NULL; } mAICount[ j ] = 0; } if ( mNumRegisteredAI > 0 ) { for ( i = 0; i < mNumRegisteredAI; ++i ) { mRegisteredVehicles[ i ].mVehicle->Release(); mRegisteredVehicles[ i ].mVehicle = NULL; } } mNumRegisteredAI = 0; for( i = 0; i < mTriggerCount; i++ ) { mTriggerVolumes[ i ]->Release(); mTriggerVolumes[ i ] = NULL; } mTriggerCount = 0; } //============================================================================= // TriggerVolumeTracker::Update //============================================================================= // Description: Comment // // Parameters: ( int elapsedTime ) // // Return: void // //============================================================================= void TriggerVolumeTracker::Update( int elapsedTime ) { if ( mIgnoreTriggers ) { //Do nothing return; } BEGIN_PROFILE("Trigger Tracker"); rmt::Vector center; const float radius = 1.0f; unsigned int iNumPlayers = GetGameplayManager()->GetNumPlayers(); unsigned int i; for( i = 0; i < iNumPlayers; i++ ) { // get the player's location and bounding sphere radius GetAvatarManager()->GetAvatarForPlayer( i )->GetPosition( center ); CheckForActiveVolumes( i, center, radius ); } VehicleCentral* vc = GetVehicleCentral(); for ( i = 0; i < mNumRegisteredAI; ++i ) { rmt::Vector pos; mRegisteredVehicles[ i ].mVehicle->GetPosition( &pos ); int id = vc->GetVehicleId( mRegisteredVehicles[ i ].mVehicle ); CheckForActiveVolumes( id + MAX_PLAYERS, pos, radius ); } END_PROFILE("Trigger Tracker"); } //============================================================================= // TriggerVolumeTracker::AddTrigger //============================================================================= // Description: Comment // // Parameters: ( TriggerVolume* triggerVolume ) // // Return: void // //============================================================================= void TriggerVolumeTracker::AddTrigger( TriggerVolume* triggerVolume ) { rAssert( mTriggerCount < MAX_VOLUMES ); unsigned int index; for( index = 0; index < mTriggerCount; index++ ) { if( mTriggerVolumes[ index ] == triggerVolume ) { return; } } mTriggerVolumes[ mTriggerCount ] = triggerVolume; triggerVolume->AddRef(); mTriggerCount++; } //============================================================================= // TriggerVolumeTracker::RemoveTrigger //============================================================================= // Description: Comment // // Parameters: ( TriggerVolume* triggerVolume ) // // Return: void // //============================================================================= void TriggerVolumeTracker::RemoveTrigger( TriggerVolume* triggerVolume ) { unsigned int index; for( index = 0; index < mTriggerCount; index++ ) { if( mTriggerVolumes[ index ] == triggerVolume ) { //Shift the last trigger into the new empty position. mTriggerVolumes[ index ] = mTriggerVolumes[ mTriggerCount-1 ]; triggerVolume->Release(); mTriggerCount--; break; } } for( int player = 0; player < GetGameplayManager()->GetNumPlayers(); player++ ) { for( index = 0; index < mActiveCount[ player ]; index++ ) { if( mActiveVolumes[ player ][ index ] == triggerVolume ) { RemoveActive( player, index ); break; } } } for ( unsigned int ai = 0; ai < mNumRegisteredAI; ++ai ) { for ( index = 0; index < mAICount[ ai ]; ++index ) { if ( mActiveAIVolumes[ ai ][ index ] == triggerVolume ) { RemoveAIActive( ai, index ); } } } } //============================================================================= // TriggerVolumeTracker::UnregisterFromInventory //============================================================================= // Description: Comment // // Parameters: ( tInventory* inv ) // // Return: void // //============================================================================= void TriggerVolumeTracker::UnregisterFromInventory( tInventory* inv ) { //BEGIN_PROFILE( "Trigger Tracker Unregister Inventory "); rAssert( inv ); if ( inv ) { HeapMgr()->PushHeap( GMA_TEMP ); tInventory::Iterator it; HeapMgr()->PopHeap( GMA_TEMP ); TriggerVolume* tv = it.First(); while ( tv != NULL ) { RemoveTrigger( tv ); tv = it.Next(); } } //END_PROFILE( "Trigger Tracker Unregister Inventory "); } //============================================================================= // TriggerVolumeTracker::HandleEvent //============================================================================= // Description: Comment // // Parameters: ( EventEnum id, void* pEventData ) // // Return: void // //============================================================================= void TriggerVolumeTracker::HandleEvent( EventEnum id, void* pEventData ) { switch( id ) { case EVENT_LOCATOR: { break; } default: { // implement all events this class is registered for! rAssert( false ); } } } //============================================================================= // TriggerVolumeTracker::Render //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void TriggerVolumeTracker::Render() { #ifndef RAD_RELEASE const Locator* locator; unsigned int i; /* Avatar* playerAvatar = GetAvatarManager()->GetAvatarForPlayer( 0 ); rAssert( playerAvatar ); if ( playerAvatar->IsInCar() ) { //Test the car like it was the "Green Lantern" | 0 |. Two lines and //a sphere. //Get the BBOX of the car Vehicle* vehicle = playerAvatar->GetVehicle(); sim::CollisionVolume* vecol = vehicle->GetSimState()->GetCollisionObject()->GetCollisionVolume()->GetSubCollisionVolume( 0 ); rAssert( vecol->Type() == sim::OBBoxVolumeType ); sim::OBBoxVolume* obBox = static_cast( vecol ); rmt::Vector minCorner, maxCorner; minCorner.x = - obBox->mLength[0]; minCorner.y = - obBox->mLength[1]; minCorner.z = - obBox->mLength[2]; maxCorner.x = obBox->mLength[0]; maxCorner.y = obBox->mLength[1]; maxCorner.z = obBox->mLength[2]; p3d::stack->Push(); rmt::Matrix positionMatrix; positionMatrix.Identity(); positionMatrix.Row(0) = obBox->mAxis[0]; positionMatrix.Row(1) = obBox->mAxis[1]; positionMatrix.Row(2) = obBox->mAxis[2]; positionMatrix.Row(3) = obBox->mPosition; p3d::stack->Multiply(positionMatrix); tShader* shader = new tShader("simple"); shader->AddRef(); P3DDrawOrientedBox( minCorner, maxCorner, *shader ); shader->Release(); p3d::stack->Pop(); } */ for( i = 0; i < mTriggerCount; i++ ) { if ( mDisplayAll ) { mTriggerVolumes[ i ]->Render(); continue; } locator = mTriggerVolumes[ i ]->GetLocator(); if ( CommandLineOptions::Get( CLO_SHOW_DYNA_ZONES ) && locator->GetDataType() == LocatorType::DYNAMIC_ZONE ) { mTriggerVolumes[ i ]->Render(); } else if ( !locator ) { } else if ( mDisplayActive && locator->GetFlag( Locator::ACTIVE ) ) { if ( mDisplayEnable[ locator->GetDataType() ] ) { mTriggerVolumes[ i ]->Render(); } else if ( locator->GetDataType() == LocatorType::EVENT ) { //We want to look at the ambient events. EventLocator* evtLoc = (EventLocator*)( locator ); LocatorEvent::Event event = evtLoc->GetEventType(); if ( mDisplayAmbients && (( event >= LocatorEvent::AMBIENT_SOUND_CITY && event <= LocatorEvent::AMBIENT_SOUND_MANSION_INTERIOR ) || ( event >= LocatorEvent::AMBIENT_SOUND_COUNTRY_NIGHT && event <= LocatorEvent::AMBIENT_SOUND_PLACEHOLDER9 ) || ( event >= LocatorEvent::AMBIENT_SOUND_SEASIDE_NIGHT && event <= LocatorEvent::AMBIENT_SOUND_PLACEHOLDER16 )) ) { mTriggerVolumes[ i ]->Render(); } } } else if ( mDisplayInactive && !locator->GetFlag( Locator::ACTIVE ) ) { if ( mDisplayEnable[ locator->GetDataType() ] ) { mTriggerVolumes[ i ]->Render(); } } } /* rmt::Vector center; GetAvatarManager()->GetAvatarForPlayer( 0 )->GetPosition( center ); IntersectManager* im = IntersectManager::GetInstance(); rAssert( im ); ReserveArray volDSGList; //float radius = GetSuperCamManager()->GetSCC( 0 )->GetActiveSuperCam()->GetFarPlane(); float radius = 180.0f; im->FindTrigVolElems( center, radius, volDSGList ); unsigned int time = radTimeGetMilliseconds(); //Test all the triggers around the car for ( i = 0; i < static_cast(volDSGList.mUseSize); ++i ) { TriggerVolume* vol = volDSGList[ i ]; if ( mDisplayAll ) { vol->Render(); continue; } locator = vol->GetLocator(); if ( mDisplayActive && locator->GetFlag( Locator::ACTIVE ) ) { if ( mDisplayEnable[ locator->GetDataType() ] ) { vol->Render(); } } else if ( mDisplayInactive && !locator->GetFlag( Locator::ACTIVE ) ) { if ( mDisplayEnable[ locator->GetDataType() ] ) { vol->Render(); } } } */ #endif } //============================================================================= // TriggerVolumeTracker::GetTriggerByName //============================================================================= // Description: Comment // // Parameters: ( const char* name ) // // Return: TriggerVolume // //============================================================================= TriggerVolume* TriggerVolumeTracker::GetTriggerByName( const char* name ) { unsigned int i; for( i = 0; i < mTriggerCount; i++ ) { if( strcmp( name, mTriggerVolumes[ i ]->GetName() ) == 0 ) { return( mTriggerVolumes[ i ] ); } } return( NULL ); } //============================================================================= // TriggerVolumeTracker::RegisterAI //============================================================================= // Description: Comment // // Parameters: ( Vehicle* ai, int locatorTypes ) // // Return: void // //============================================================================= void TriggerVolumeTracker::RegisterAI( Vehicle* ai, int locatorTypes ) { rAssert( mNumRegisteredAI < MAX_AI ); #ifdef RAD_DEBUG unsigned int i; for ( i = 0; i < mNumRegisteredAI; ++i ) { rAssert( mRegisteredVehicles[ i ].mVehicle != ai ); } #endif if ( mNumRegisteredAI < MAX_AI ) { tRefCounted::Assign( mRegisteredVehicles[ mNumRegisteredAI ].mVehicle, ai ); mRegisteredVehicles[ mNumRegisteredAI ].mTriggerTypes = locatorTypes; } mNumRegisteredAI++; } //============================================================================= // TriggerVolumeTracker::UnregisterAI //============================================================================= // Description: Comment // // Parameters: ( Vehicle* ai ) // // Return: void // //============================================================================= void TriggerVolumeTracker::UnregisterAI( Vehicle* ai ) { unsigned int i; for ( i = 0; i < mNumRegisteredAI; ++i ) { if ( mRegisteredVehicles[ i ].mVehicle == ai ) { mRegisteredVehicles[ i ].mVehicle->Release(); mRegisteredVehicles[ i ].mVehicle = NULL; if ( mNumRegisteredAI > 1 ) { mRegisteredVehicles[ i ] = mRegisteredVehicles[ mNumRegisteredAI - 1 ]; mRegisteredVehicles[ mNumRegisteredAI - 1 ].mVehicle = NULL; } mNumRegisteredAI -= 1; break; } } } //============================================================================= // TriggerVolumeTracker::GetAI //============================================================================= // Description: Comment // // Parameters: ( int id ) // // Return: Vehicle // //============================================================================= Vehicle* TriggerVolumeTracker::GetAI( int id ) { rAssert( id - MAX_PLAYERS < static_cast(mNumRegisteredAI) ); return mRegisteredVehicles[ id - MAX_PLAYERS ].mVehicle; } //============================================================================= // TriggerVolumeTracker::RegisterLocatorTypeForAI //============================================================================= // Description: Comment // // Parameters: ( LocatorType::Type type, Vehicle* ai ) // // Return: void // //============================================================================= void TriggerVolumeTracker::RegisterLocatorTypeForAI( LocatorType::Type type, Vehicle* ai ) { unsigned int i; for ( i = 0; i < mNumRegisteredAI; ++i ) { if ( mRegisteredVehicles[ i ].mVehicle == ai ) { mRegisteredVehicles[ i ].mTriggerTypes |= ( 1 << type ); break; } } } //============================================================================= // TriggerVolumeTracker::UnregisterLocatorTypeForAI //============================================================================= // Description: Comment // // Parameters: ( LocatorType::Type type, Vehicle* ai ) // // Return: void // //============================================================================= void TriggerVolumeTracker::UnregisterLocatorTypeForAI( LocatorType::Type type, Vehicle* ai ) { unsigned int i; for ( i = 0; i < mNumRegisteredAI; ++i ) { if ( mRegisteredVehicles[ i ].mVehicle == ai ) { mRegisteredVehicles[ i ].mTriggerTypes &= ~( 1 << type ); break; } } } //============================================================================= // TriggerVolumeTracker::ResetDynaloadZones //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void TriggerVolumeTracker::ResetDynaloadZones() { for( int player = 0; player < GetGameplayManager()->GetNumPlayers(); player++ ) { for( int index = 0; index < static_cast( mActiveCount[ player ] ); index++ ) { Locator* loc = mActiveVolumes[ player ][ index ]->GetLocator(); if ( !loc ) { continue; } if( loc->GetDataType() == LocatorType::DYNAMIC_ZONE ) { RemoveActive( player, index ); break; } } } } //======================================================================== // triggervolumetracker:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void TriggerVolumeTracker::ActivateNearestInteriorLoadZone(int iPlayerID, rmt::Vector& irPosnRef, float iMaxDistance) { ZoneEventLocator* pNearestZEL = NULL; float nearestLocatorDistSqr = iMaxDistance*iMaxDistance; Locator* loc = NULL; rmt::Sphere sphere; int i; for ( i = 0; i < static_cast( mTriggerCount ); ++i ) { loc = mTriggerVolumes[i]->GetLocator(); if(loc == NULL) continue; if( loc->GetDataType() == LocatorType::DYNAMIC_ZONE ) { ZoneEventLocator* pZEL = (ZoneEventLocator*)(loc); if(pZEL->IsInteriorLoad()) { mTriggerVolumes[i]->GetBoundingSphere(&sphere); rmt::Vector dist; dist.Sub(sphere.centre, irPosnRef); float curDistSqr = dist.MagnitudeSqr(); if( (curDistSqr < nearestLocatorDistSqr) && (curDistSqr < ((iMaxDistance + sphere.radius) * (iMaxDistance + sphere.radius)))) { pNearestZEL = pZEL; nearestLocatorDistSqr = curDistSqr; } } } } if(pNearestZEL!=NULL) { pNearestZEL->Trigger(iPlayerID,true); } } //****************************************************************************** // // Private Member Functions // //****************************************************************************** //============================================================================= // TriggerVolumeTracker::AddActive //============================================================================= // Description: Comment // // Parameters: ( int playerID, TriggerVolume* triggerVolume ) // // Return: void // //============================================================================= void TriggerVolumeTracker::AddActive( int playerID, TriggerVolume* triggerVolume ) { rAssert( triggerVolume != NULL ); if ( triggerVolume == NULL || !triggerVolume->TriggerAllowed( playerID ) ) return; rAssert( mActiveCount[ playerID ] < MAX_ACTIVE ); mActiveVolumes[ playerID ][ mActiveCount[ playerID ] ] = triggerVolume; mActiveCount[ playerID ]++; triggerVolume->AddRef(); TriggerLocator* trigLoc = triggerVolume->GetLocator(); if ( trigLoc && trigLoc->IsPlayerTracked( playerID ) == 0 ) //returns number tracked. { triggerVolume->Trigger( playerID, true ); } triggerVolume->SetTrackingPlayer( playerID, true ); } //============================================================================= // TriggerVolumeTracker::CheckForActiveVolumes //============================================================================= // Description: Comment // // Parameters: ( int playerID, rmt::Vector& center, float radius ) // // Return: void // //============================================================================= void TriggerVolumeTracker::CheckForActiveVolumes( int playerID, rmt::Vector& center, float radius ) { unsigned int time = radTimeGetMilliseconds(); unsigned int i; //BEGIN_PROFILE( "CheckForActiveVolumes" ); // IntersectManager* im = IntersectManager::GetInstance(); // rAssert( im ); // // ReserveArray volDSGList; // //BEGIN_PROFILE( "Query Intersect Manager" ); // im->FindTrigVolElems( center, radius, volDSGList ); //END_PROFILE( "Query Intersect Manager" ); //BEGIN_PROFILE( "Car Triggers" ); //Test all the triggers around the car // for ( i = 0; i < static_cast(volDSGList.mUseSize); ++i ) // { // TriggerVolume* vol = volDSGList[ i ]; // // TestVolume( vol, center, radius, playerID, time ); // } //END_PROFILE( "Car Triggers" ); int localID = playerID; if ( playerID >= MAX_PLAYERS ) { //localize the id VehicleCentral* vc = GetVehicleCentral(); for ( i = 0; i < mNumRegisteredAI; ++i ) { if ( mRegisteredVehicles[ i ].mVehicle == vc->GetVehicle( playerID - MAX_PLAYERS ) ) { localID = i + MAX_PLAYERS; break; } } rAssert( localID != -1 ); } else { //This is a player. Store their points for testing. //Test the car like it was the "Green Lantern" | 0 |. Two lines and //a sphere. //Get the BBOX of the car Avatar* playerAvatar = GetAvatarManager()->GetAvatarForPlayer( playerID ); Vehicle* vehicle = playerAvatar->GetVehicle(); if ( vehicle ) { /* rmt::Vector box = vehicle->GetExtents(); rmt::Matrix carToWorld = vehicle->GetTransform(); sP1.x = -box.x; sP1.y = -box.y; sP1.z = -box.z; sP1.Transform( carToWorld ); sP2.x = +box.x; sP2.y = -box.y; sP2.z = -box.z; sP2.Transform( carToWorld ); sP3.x = +box.x; sP3.y = +box.y; sP3.z = +box.z; sP3.Transform( carToWorld ); sP4.x = -box.x; sP4.y = +box.y; sP4.z = +box.z; sP4.Transform( carToWorld ); */ sim::CollisionVolume* vecol = vehicle->GetSimState()->GetCollisionObject()->GetCollisionVolume()->GetSubCollisionVolume( 0 ); sColType = vecol->Type(); if( sColType == sim::OBBoxVolumeType ) { sim::OBBoxVolume* obBox = static_cast( vecol ); sP1.x = - obBox->mLength[0]; sP1.y = - obBox->mLength[1]; sP1.z = - obBox->mLength[2]; sP2.x = obBox->mLength[0]; sP2.y = - obBox->mLength[1]; sP2.z = - obBox->mLength[2]; sP3.x = obBox->mLength[0]; sP3.y = obBox->mLength[1]; sP3.z = obBox->mLength[2]; sP4.x = - obBox->mLength[0]; sP4.y = obBox->mLength[1]; sP4.z = obBox->mLength[2]; rmt::Matrix positionMatrix; positionMatrix.Identity(); positionMatrix.Row(0) = obBox->mAxis[0]; positionMatrix.Row(1) = obBox->mAxis[1]; positionMatrix.Row(2) = obBox->mAxis[2]; positionMatrix.Row(3) = obBox->mPosition; sP1.Transform( positionMatrix ); sP2.Transform( positionMatrix ); sP3.Transform( positionMatrix ); sP4.Transform( positionMatrix ); radius = rmt::Sqrt(obBox->mLength[0] + obBox->mLength[1]); } } } //BEGIN_PROFILE( "Added Triggers" ); //Test all the triggers added to the trigger tracker for ( i = 0; i < mTriggerCount; ++i ) { rmt::Sphere sphere; mTriggerVolumes[ i ]->GetBoundingSphere(&sphere); rmt::Vector dist; dist.Sub(sphere.centre, center); if(dist.MagnitudeSqr() < ((radius + sphere.radius) * (radius + sphere.radius))) { TestVolume( mTriggerVolumes[ i ], center, radius, localID, time ); } } //END_PROFILE( "Added Triggers" ); if ( playerID < MAX_PLAYERS ) { //BEGIN_PROFILE( "Active Triggers" ); //Test for triggers that we've left. for( i = 0; i < mActiveCount[ playerID ]; ++i ) { // Added a test for the active trigger volume, because it would // seem that if a locator were not active, you wouldn't want // the TV in the active list. // // TBJ [8/23/2002] // if( (mActiveVolumes[ playerID ][ i ]->GetLocator() && !mActiveVolumes[ playerID ][ i ]->GetLocator()->GetFlag( Locator::ACTIVE )) || mActiveVolumes[ playerID ][ i ]->GetFrameUsed() != time ) { RemoveActive( playerID, i ); } } //END_PROFILE( "Active Triggers" ); } else { localID -= MAX_PLAYERS; for ( i = 0; i < mAICount[ localID ]; ++i ) { if ( !mActiveAIVolumes[ localID ][ i ]->GetLocator()->GetFlag( Locator::ACTIVE ) || mActiveAIVolumes[ localID ][ i ]->GetFrameUsed() != time ) { RemoveAIActive( localID, i ); } } } //END_PROFILE( "CheckForActiveVolumes" ); } //============================================================================= // TriggerVolumeTracker::RemoveActive //============================================================================= // Description: Comment // // Parameters: ( int playerID, int index ) // // Return: void // //============================================================================= void TriggerVolumeTracker::RemoveActive( int playerID, int index ) { TriggerVolume* vol = mActiveVolumes[ playerID ][ index ]; TriggerLocator* trigLoc = vol->GetLocator(); if ( trigLoc && trigLoc->IsPlayerTracked( playerID ) <= 1 ) //Some locators are screwy so they never track trigger voluemes. Gags, mostly { vol->Trigger( playerID, false ); } vol->SetTrackingPlayer( playerID, false ); vol->Release(); if ( mActiveCount[ playerID ] > 0 ) { mActiveVolumes[ playerID ][ index ] = mActiveVolumes[ playerID ][ mActiveCount[ playerID ] - 1 ]; mActiveVolumes[ playerID ][ mActiveCount[ playerID ] - 1 ] = NULL; } mActiveCount[ playerID ]--; } //============================================================================= // TriggerVolumeTracker::AddAIActive //============================================================================= // Description: Comment // // Parameters: ( int playerID, TriggerVolume* triggerVolume ) // // Return: void // //============================================================================= void TriggerVolumeTracker::AddAIActive( int playerID, TriggerVolume* triggerVolume ) { rAssert( mAICount[ playerID ] < MAX_AI_VOLUMES ); if ( !triggerVolume->TriggerAllowed( playerID ) ) { return; } mActiveAIVolumes[ playerID ][ mAICount[ playerID ] ] = triggerVolume; triggerVolume->AddRef(); TriggerLocator* trigLoc = triggerVolume->GetLocator(); if ( trigLoc && trigLoc->IsPlayerTracked( playerID + MAX_PLAYERS ) == 0 ) { triggerVolume->Trigger( playerID + MAX_PLAYERS, true ); //And the hacks go on } triggerVolume->SetTrackingPlayer( playerID + MAX_PLAYERS, true ); mAICount[ playerID ] += 1; } //============================================================================= // TriggerVolumeTracker::RemoveAIActive //============================================================================= // Description: Comment // // Parameters: ( int playerID, int index ) // // Return: void // //============================================================================= void TriggerVolumeTracker::RemoveAIActive( int playerID, int index ) { TriggerVolume* vol = mActiveAIVolumes[ playerID ][ index ]; TriggerLocator* trigLoc = vol->GetLocator(); if ( trigLoc && trigLoc->IsPlayerTracked( playerID + MAX_PLAYERS ) == 1 ) { vol->Trigger( playerID + MAX_PLAYERS, false ); } vol->SetTrackingPlayer( playerID + MAX_PLAYERS, false ); //This is a hack. vol->Release(); if ( mAICount[ playerID ] > 0 ) { mActiveAIVolumes[ playerID ][ index ] = mActiveAIVolumes[ playerID ][ mAICount[ playerID ] - 1 ]; mActiveAIVolumes[ playerID ][ mAICount[ playerID ] - 1 ] = NULL; } mAICount[ playerID ] -= 1; } //============================================================================= // TriggerVolumeTracker::TestVolume //============================================================================= // Description: Comment // // Parameters: ( TriggerVolume* vol, rmt::Vector& center, float radius, int playerID, unsigned int time ) // // Return: void // //============================================================================= void TriggerVolumeTracker::TestVolume( TriggerVolume* vol, rmt::Vector& center, float radius, int playerID, unsigned int time ) { rAssert( vol ); // This is added because the AmbientDialogueTriggers do not have a locator associated with them // with them. if ( vol->GetLocator() != NULL ) { if ( playerID >= MAX_PLAYERS && ( ((1 << vol->GetLocator()->GetDataType()) & mRegisteredVehicles[ playerID - MAX_PLAYERS ].mTriggerTypes) == 0 ) ) { return; } else if ( playerID >= MAX_PLAYERS ) { //Test if this is a legal event. if ( vol->GetLocator()->GetDataType() == LocatorType::EVENT ) { EventLocator* evtLoc = static_cast(vol->GetLocator()); unsigned int i; for ( i = 0; i < NUM_ALLOWED_AI_EVENTS; ++i ) { if ( evtLoc->GetEventType() == ALLOWED_AI_EVENTS[ i ] ) { break; } } if ( i == NUM_ALLOWED_AI_EVENTS ) { //Not allowed to trigger this. return; } } } } bool collision = false; Locator* loc = vol->GetLocator(); if ( playerID < MAX_PLAYERS && GetAvatarManager()->GetAvatarForPlayer( playerID )->IsInCar() && ( loc && loc->GetDataType() != LocatorType::OCCLUSION ) ) { if ( GetGameplayManager()->GetGameType() == GameplayManager::GT_SUPERSPRINT ) { collision = (!loc || loc->GetFlag( Locator::ACTIVE )) && vol->IntersectsSphere( center, 1.5f ); } else { collision = (!loc || loc->GetFlag( Locator::ACTIVE )) && (vol->IntersectsSphere( center, 1.5f ) || vol->IntersectsBox( sP1, sP2, sP4, sP3 )); } } else { collision = (!loc || loc->GetFlag( Locator::ACTIVE )) && vol->Contains( center, radius ); } //BEGIN_PROFILE( "Test Volume" ); if ( collision ) { //Test to see if this is a DEATH volume. if ( loc->GetDataType() == LocatorType::EVENT ) { EventLocator* evtLoc = static_cast(loc); if ( evtLoc->GetEventType() == LocatorEvent::DEATH ) { //This is so that death volumes always say you're in them until you leave. //Hack for Chuka. vol->Trigger( playerID, true ); return; //Early death. } } //BEGIN_PROFILE( "Is Player Tracking" ); if ( !vol->IsPlayerTracking( playerID ) ) { //New trigger! #ifdef RAD_DEBUG char name[256]; sprintf(name, "Hit trigger: %s\n", vol->GetName() ); rDebugString( name ); #endif if ( playerID < MAX_PLAYERS ) { //BEGIN_PROFILE( "AddActive" ); AddActive( playerID, vol ); //END_PROFILE( "AddActive" ); } else { AddAIActive( playerID - MAX_PLAYERS, vol ); } } vol->SetFrameUsed( time, (int)this ); } //END_PROFILE( "Test Volume" ); }