//============================================================================= // Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. // // File: missionobjective.cpp // // Description: Implement MissionObjective // // History: 15/04/2002 + Created -- NAME // //============================================================================= //======================================== // System Includes //======================================== // Foundation Tech #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 //****************************************************************************** // // Global Data, Local Data, Local Classes // //****************************************************************************** //****************************************************************************** // // Public Member Functions // //****************************************************************************** //============================================================================== // MissionObjective::MissionObjective //============================================================================== // Description: Constructor. // // Parameters: None. // // Return: N/A. // //============================================================================== MissionObjective::MissionObjective() : mObjType( OBJ_INVALID ), mbFinished( false ), mVehicle( NULL ), mNumNPCs( 0 ), mNumRemoveNPCs( 0 ), mRockOut( false ) { } //============================================================================== // MissionObjective::~MissionObjective //============================================================================== // Description: Destructor. // // Parameters: None. // // Return: N/A. // //============================================================================== MissionObjective::~MissionObjective() { } bool MissionObjective::AddNPCWaypoint( const char* npc, const char* location ) { rTuneAssert( npc ); rTuneAssert( location ); for( unsigned int i = 0; i < mNumNPCs; ++i ) { if( strcmp( mNPCNames[i], npc ) == 0 ) { int numWays = mNPCs[i].numWayLocs; rAssert( numWays >= 0 ); // add only if we have room if( numWays >= (MAX_NPC_WAYPOINT_LOCATORS - 1) ) { #if (RAD_TUNE || RAD_DEBUG) char errMsg[ 256 ]; sprintf( errMsg, "Cannot add more NPC waypoints for %s", npc ); rTuneAssertMsg( false, errMsg ); #endif return false; } mNPCs[i].wayLocs[ numWays ].SetText( location ); mNPCs[i].numWayLocs++; return true; } } // if we got here, the npc is not in our list. return false; } //============================================================================= // MissionObjective::Initalize //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void MissionObjective::Initialize() { #if defined(RAD_DEBUG) || defined(RAD_TUNE) char errMsg[ 256 ]; #endif // // Trigger an event that this objective is now active // GetEventManager()->TriggerEvent( EVENT_MISSION_OBJECTIVE_NEW, reinterpret_cast< void* >( this ) ); mbFinished = false; //Move the required NPCs to their new locations and store their old pos/rot. unsigned int i; for(i = 0; i < mNumRemoveNPCs; i++) { char name[64]; if(mRemoveNPCs[i].driver) { sprintf(name, "d_%s", mRemoveNPCs[i].name); } else { strcpy(name, mRemoveNPCs[i].name); } Character* c = GetCharacterManager()->GetCharacterByName(name); if(c) { if(c->IsAmbient()) { c->ResetAmbientPosition(); } else { if(mRemoveNPCs[i].driver && c->GetTargetVehicle()) { c->GetTargetVehicle()->SetDriver(NULL); } GetCharacterManager()->RemoveCharacter(c); } } } for ( i = 0; i < mNumNPCs; ++i ) { if(mNPCs[ i ].driver) { Vehicle* vehicle = GetGameplayManager()->GetMissionVehicleByName(mNPCs[ i ].locator); char name[64]; sprintf(name, "d_%s", mNPCNames[i]); Character* character = GetCharacterManager( )->GetCharacterByName(name); if(character && (character->GetTargetVehicle() == vehicle)) { continue; } if(character) { GetCharacterManager()->RemoveCharacter(character); } character = GetCharacterManager()->AddCharacter(CharacterManager::NPC, name, mNPCNames[i], "npd", NULL ); static_cast(character->GetController())->TransitToState(NPCController::NONE); character->SetTargetVehicle( vehicle ); character->AddToWorldScene(); character->GetStateManager()->SetState(); vehicle->SetDriver(character); character->SetRole(Character::ROLE_DRIVER); } else { // pick an appropriate name based on if we are a bonus mission or not bool hadToAdd = false; mNPCs[ i ].npc = GetCharacterManager( )->GetMissionCharacter(mNPCNames[i]); if( !mNPCs[ i ].npc ) { char name[64]; hadToAdd = true; if(GetGameplayManager()->GetCurrentMission()->IsBonusMission()) { sprintf(name, "b_%s", mNPCNames[i]); } else { strcpy(name, mNPCNames[i]); } mNPCs[ i ].npc = GetCharacterManager()->AddCharacter(CharacterManager::NPC, name, mNPCNames[i], "npd", NULL ); mNPCs[ i ].npc->SetRole(Character::ROLE_MISSION); } else { mNPCs[ i ].npc->EnableAmbientDialogue(false); } rAssert( mNPCs[ i ].npc ); CarStartLocator* newPos = p3d::find(mNPCs[ i ].locator); // TODO : is this neccesary mNPCs[ i ].npc->RemoveFromWorldScene(); mNPCs[ i ].npc->AddToWorldScene(); GetCharacterManager( )->SetGarbage(mNPCs[ i ].npc, false); mNPCs[ i ].npc->AddRef(); NPCController* controller = (NPCController*) (mNPCs[ i ].npc->GetController()); rAssert( controller ); // set position & facing // if we have no locator, just leave them where they are if(newPos) { rmt::Vector oldpos, pos, dist; newPos->GetLocation(&pos); mNPCs[ i ].npc->GetPosition(oldpos); dist.Sub(pos, oldpos); bool loading = ((GetGuiSystem()->GetBackendManager()->GetCurrentScreen() == CGuiWindow::GUI_SCREEN_ID_LOADING) && GetGuiSystem()->GetBackendManager()->GetCurrentWindow()->IsRunning()); if(hadToAdd || (dist.Magnitude() > 20.0f) || ((GetGameFlow()->GetCurrentContext() == CONTEXT_LOADING_GAMEPLAY) || loading)) { mNPCs[ i ].npc->RelocateAndReset( pos, newPos->GetRotation() ); if(!hadToAdd) { if(mNPCs[ i ].npc->GetRole() != Character::ROLE_MISSION) { controller->SetTempWaypont(pos); } } } // add the start locator as the first waypoint if((mNPCs[ i ].npc->GetRole() == Character::ROLE_MISSION)) { controller->ClearNPCWaypoints(); bool res = controller->AddNPCWaypoint( pos ); #if defined(RAD_DEBUG) || defined(RAD_TUNE) sprintf( errMsg, "Can't add more waypoints for this objective NPC %s", mNPCNames[ i ] ); rTuneAssertMsg( res, errMsg ); #endif } } else { #if defined(RAD_DEBUG) || defined(RAD_TUNE) // for existing characters it's okay not to have a locator, // but for new ones, its an error sprintf( errMsg, "NPC %s created without valid locator (%s). Check spelling!\n", mNPCNames[i], mNPCs[ i ].locator); rTuneAssertMsg( false, errMsg ); #endif } if(mNPCs[ i ].npc->GetRole() == Character::ROLE_MISSION) { for( int j=0; j( mNPCs[ i ].wayLocs[ j ].GetUID() ); if( loc == NULL ) { #if defined(RAD_DEBUG) || defined(RAD_TUNE) sprintf( errMsg, "NPC Waypoint %s not found for NPC %s", mNPCs[ i ].wayLocs[ j ].GetText(), mNPCNames[ i ] ); rTuneAssertMsg( false, errMsg ); #endif continue; } rmt::Vector locPos; loc->GetPosition( &locPos ); // the NPCController is created and assigned to the NPC in // then NPCharacter constructor. So we should expect there // to be a controller at this point bool res = controller->AddNPCWaypoint( locPos ); #if defined(RAD_DEBUG) || defined(RAD_TUNE) sprintf( errMsg, "Can't add more waypoints for this objective NPC %s", mNPCNames[ i ] ); rTuneAssertMsg( res, errMsg ); #endif } } } } GetCharacterManager()->AllowGarbageCollection(true); GetCharacterManager()->GetCharacter(0)->SetRockinIdle(mRockOut); OnInitialize(); } //============================================================================= // MissionObjective::Finalize //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void MissionObjective::Finalize() { OnFinalize(); GetCharacterManager()->GetCharacter(0)->SetRockinIdle(false); //return all NPCs to their original locations. unsigned int i; for ( i = 0; i < mNumNPCs; ++i ) { if( mNPCs[ i ].driver) { continue; } rAssert( mNPCs[ i ].npc ); // make all NPC's in this mission canidates for garbage colleciton GetCharacterManager( )->SetGarbage(mNPCs[ i ].npc, true); /*** mNPCs[ i ].npc->SetPosition( mNPCs[ i ].oldPos ); mNPCs[ i ].npc->SetFacingDir( mNPCs[ i ].oldRotation ); mNPCs[ i ].npc->UpdateTransformToLoco(); ***/ mNPCs[ i ].npc->Release(); mNPCs[ i ].npc = NULL; } GetCharacterManager()->AllowGarbageCollection(false); } //============================================================================= // MissionObjective::Update //============================================================================= // Description: Comment // // Parameters: ( float elapsedTime ) // // Return: void // //============================================================================= void MissionObjective::Update( unsigned int elapsedTime ) { OnUpdate( elapsedTime ); } //============================================================================= // MissionObjective::HandleEvent //============================================================================= // Description: Comment // // Parameters: ( EventEnum id, void* pEventData ) // // Return: void // //============================================================================= void MissionObjective::HandleEvent( EventEnum id, void* pEventData ) { } //============================================================================= // MissionObjective::AddNPC //============================================================================= // Description: Comment // // Parameters: ( const char* name, CarStartLocator* newPos ) // // Return: void // //============================================================================= void MissionObjective::AddNPC( const char* name, const char* loc, bool driver) { #if (RAD_TUNE || RAD_DEBUG) char errMsg[ 128 ]; rTuneAssertMsg( name, "An NPC's name can't be null!" ); sprintf( errMsg, "Locator for NPC %s cannot be null!", name ); rTuneAssertMsg( loc, errMsg ); sprintf( errMsg, "Can't add more NPCs. Already reached max count of %d.", mNumNPCs ); rTuneAssertMsg( mNumNPCs < (MAX_NPCS - 1), errMsg ); #endif //Add the NPC name to the list. unsigned int len = strlen(name) < MAX_NPC_NAME_LENGTH - 1 ? strlen(name) : MAX_NPC_NAME_LENGTH - 2; strncpy( mNPCNames[mNumNPCs], name, len ); mNPCNames[mNumNPCs][len] = '\0'; strcpy(mNPCs[ mNumNPCs ].locator, loc); // NOTE: Don't need to add the char start locator to list of waypoints here // because when AddCharacter is called on this NPC, the start locator // will be automatically added first in the list of NPC waypoints mNPCs[ mNumNPCs ].numWayLocs = 0; mNPCs[ mNumNPCs ].driver = driver; ++mNumNPCs; } void MissionObjective::RemoveNPC( const char* npc, bool driver) { rAssert(mNumRemoveNPCs < MAX_NPCS); strcpy(mRemoveNPCs[mNumRemoveNPCs].name, npc); mRemoveNPCs[mNumRemoveNPCs].driver = driver; mNumRemoveNPCs++; } //****************************************************************************** // // Private Member Functions // //****************************************************************************** //============================================================================= // MissionObjective::RegisterLocator //============================================================================= // Description: Comment // // Parameters: ( Locator* locator, int& hudIndex, bool primary, HudMapIcon::eIconType icon ) // // Return: void // //============================================================================= void MissionObjective::RegisterLocator( Locator* locator, int& hudIndex, bool primary, HudMapIcon::eIconType icon ) { rmt::Vector destLoc; locator->GetLocation( &destLoc ); RegisterPosition( destLoc, hudIndex, primary, icon, locator ); } //============================================================================= // MissionObjective::RegisterPosition //============================================================================= // Description: Comment // // Parameters: ( const rmt::Vector& pos, int& hudIndex, bool primary, HudMapIcon::eIconType icon ) // // Return: void // //============================================================================= void MissionObjective::RegisterPosition( const rmt::Vector& pos, int& hudIndex, bool primary, HudMapIcon::eIconType icon, IHudMapIconLocator* hml ) { CGuiScreenMultiHud* currentHud = GetCurrentHud(); if( currentHud ) { hudIndex = currentHud->GetHudMap( 0 )->RegisterIcon( icon, pos, hml, primary ); } } //============================================================================= // MissionObjective::UnregisterLocator //============================================================================= // Description: Comment // // Parameters: ( int hudIndex ) // // Return: void // //============================================================================= void MissionObjective::UnregisterLocator( int& hudIndex ) { // unregister hud map icon // if( hudIndex != -1 ) { CGuiScreenMultiHud* currentHud = GetCurrentHud(); if( currentHud != NULL ) { currentHud->GetHudMap( 0 )->UnregisterIcon( hudIndex ); } hudIndex = -1; } } //============================================================================= // MissionObjective::AddEntity //============================================================================= // Description: Comment // // Parameters: ( char* entityname ) // // Return: InstStatEntityDSG* // //============================================================================= InstStatEntityDSG* MissionObjective::AddEntity( char* entityname, rmt::Vector pos ) { MEMTRACK_PUSH_GROUP( "Mission - Entities" ); tDrawable* pGeometry = p3d::find( entityname ); rAssert( pGeometry != NULL ); InstStatEntityDSG* pEnt = new( GetGameplayManager()->GetCurrentMissionHeap() ) InstStatEntityDSG; rAssert( pEnt != NULL ); // // The entity takes overship of m, so spake Devin // rmt::Matrix* m = new( GetGameplayManager()->GetCurrentMissionHeap() ) rmt::Matrix; m->Identity(); m->FillTranslate( pos ); pEnt->LoadSetUp( m, pGeometry ); MEMTRACK_POP_GROUP("Mission - Entities"); return pEnt; } //============================================================================= // MissionObjective::DrawEntity //============================================================================= // Description: Comment // // Parameters: ( InstStatEntityDSG* entity ) // // Return: void // //============================================================================= void MissionObjective::DrawEntity( InstStatEntityDSG* entity ) { rAssert( entity != NULL ); GetRenderManager()->pWorldScene()->Add( entity ); } //============================================================================= // MissionObjective::HideEntity //============================================================================= // Description: Comment // // Parameters: ( InstStatEntityDSG* entity ) // // Return: void // //============================================================================= void MissionObjective::HideEntity( InstStatEntityDSG* entity ) { rAssert( entity != NULL ); GetRenderManager()->pWorldScene()->Remove( entity ); } //============================================================================= // MissionObjective::UnregisterPosition //============================================================================= // Description: Comment // // Parameters: ( int& hudIndex ) // // Return: void // //============================================================================= void MissionObjective::UnregisterPosition( int& hudIndex ) { UnregisterLocator( hudIndex ); } //============================================================================= // MissionObjective::ChangeIconType //============================================================================= // Description: Comment // // Parameters: ( int hudIndex, HudMapIcon::eIconType type ) // // Return: void // //============================================================================= int MissionObjective::ChangeIconType( int hudIndex, HudMapIcon::eIconType type ) { if( hudIndex != -1 ) { CGuiScreenMultiHud* currentHud = GetCurrentHud(); if( currentHud != NULL ) { return( currentHud->GetHudMap( 0 )->ChangeIconType( hudIndex, type ) ); } } return -1; } //============================================================================= // MissionObjective::GetObjectiveType //============================================================================= // Description: return what type of objective this is // // Parameters: none // // Return: ObjectiveTypeEnum - the type of this objective // //============================================================================= MissionObjective::ObjectiveTypeEnum MissionObjective::GetObjectiveType() const { return mObjType; } //============================================================================= // MissionObjective::SetObjectiveType //============================================================================= // Description: set the type of the objective // // Parameters: objType - the type of objective we're setting // // Return: NONE // //============================================================================= void MissionObjective::SetObjectiveType( const ObjectiveTypeEnum objType ) { mObjType = objType; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void MissionObjective::UnlightPath( SwapArray& orPathRoute ) { // rReleasePrintf("UnLightPath. 0x%x\n", orPathRoute.mpData ); int i; for(i=orPathRoute.mUseSize-1; i>-1; i-- ) { if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(false); ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false); } } for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>-1; i--) { GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->SetVisibility(false); } for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>-1; i--) { GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->SetVisibility(false); } orPathRoute.ClearUse(); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(false); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetVisibility(false); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void MissionObjective::LightCurrentPath(SwapArray& orPathRoute ) { int i; for(i=orPathRoute.mUseSize-1; i>-1; i-- ) { if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(true); ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false); } } for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>-1; i--) { GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->SetVisibility(false); } for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>-1; i--) { GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->SetVisibility(false); } GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(true); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetVisibility(false); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void MissionObjective::UnlightCurrentPath(SwapArray& orPathRoute ) { int i; for(i=orPathRoute.mUseSize-1; i>-1; i-- ) { if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(false); ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false); } } for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>-1; i--) { GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->SetVisibility(false); } for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>-1; i--) { GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->SetVisibility(false); } GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(false); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetVisibility(false); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void MissionObjective::LightPathRightWay( SwapArray& orPathRoute, int iStart, int iPastEnd ) { int i; if( DirectionalArrowEnum::INTERSECTION & mArrowType ) { iStart--; for( i=iPastEnd-1; i>iStart; i-- ) { if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(true); ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false); } } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void MissionObjective::LightPathWrongWay( SwapArray& orPathRoute, int iStart, int iPastEnd ) { int i; if( DirectionalArrowEnum::INTERSECTION & mArrowType ) { iStart--; for(i=iPastEnd; i>iStart; i-- ) { if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(false); ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(true); } } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void MissionObjective::UpdateLightPath( PathStruct& orPathStruct) { SwapArray& orPathRoute = orPathStruct.mPathRoute; if(!GetCharacterSheetManager()->QueryNavSystemSetting()) { UnlightCurrentPath(orPathRoute); return; } else { //LightCurrentPath(orPathRoute); } orPathStruct.mUpdateCount = (orPathStruct.mUpdateCount+1)%orPathStruct.msUpdateModulo; if( orPathStruct.mUpdateCount == 0 ) UpdateGroundHeights(orPathRoute); UpdateLongRoadArrows(orPathStruct); rmt::Vector charPosn, charFacing, iconPosn, iconFacing, tempVect, tempVect2; GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(charPosn); GetAvatarManager()->GetAvatarForPlayer(0)->GetHeading(charFacing); RoadManager::PathElement lastPathElem; RoadSegment* pLastRoadSegment; float lastSegmentT; float lastRoadT; int playerOnPathPosn; float distPlayerFromRoad; GetAvatarManager()->GetAvatarForPlayer(0)->GetLastPathInfo( lastPathElem, pLastRoadSegment, lastSegmentT, lastRoadT ); if(lastPathElem.type == RoadManager::ET_INTERSECTION) { playerOnPathPosn = FindIntersectionInPath( orPathRoute, (Intersection*)lastPathElem.elem ); } else { playerOnPathPosn = FindRoadInPath( orPathRoute, (Road*)lastPathElem.elem ); if(playerOnPathPosn>0) { ((Intersection*)(orPathRoute[playerOnPathPosn-1].elem))->GetLocation(tempVect); tempVect2.Sub( charPosn, tempVect ); distPlayerFromRoad = tempVect2.MagnitudeSqr(); //ensure it's out of view first, if we're setting it to red/wrong way if(distPlayerFromRoad<120.0f) playerOnPathPosn--; } } if(playerOnPathPosn!=-1) { LightPathWrongWay(orPathRoute, 0, playerOnPathPosn); LightPathRightWay(orPathRoute, playerOnPathPosn, orPathRoute.mUseSize); } /* if(FindNearestRoadIconAhead(orPathRoute, charPosn, iconPosn, iconFacing)) { charFacing.Normalize(); iconFacing.Normalize(); //if two per frame kills us, we're already dead. if(iconFacing.Dot(charFacing)>-0.3f) { LightPathRightWay(orPathRoute); } else { LightPathWrongWay(orPathRoute); } } else { // rAssert(false); } */ } //======================================================================== // missionobjective:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== int MissionObjective::FindIntersectionInPath(SwapArray& irPath, Intersection* ipIntToFind) { // // Determine whether the players on the path that we want to light. // for(int i=irPath.mUseSize-1; i>-1; i--) { if(irPath[i].elem == ipIntToFind) return i; } return -1; } //======================================================================== // missionobjective:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== int MissionObjective::FindRoadInPath(SwapArray& irPath, Road* ipRoadToFind) { // // Determine whether the players on the path that we want to light. // for(int i=irPath.mUseSize-1; i>-1; i--) { if(irPath[i].type == RoadManager::ET_INTERSECTION) continue; if( (((Road*)(irPath[i].elem))->GetSourceIntersection() == ipRoadToFind->GetSourceIntersection() && ((Road*)(irPath[i].elem))->GetDestinationIntersection() == ipRoadToFind->GetDestinationIntersection()) || (((Road*)(irPath[i].elem))->GetSourceIntersection() == ipRoadToFind->GetDestinationIntersection() && ((Road*)(irPath[i].elem))->GetDestinationIntersection() == ipRoadToFind->GetSourceIntersection()) ) //found matching path { return i; } } return -1; } ////////////////////////////////////////////////////////////////////////// // MissionObjective::UpdateGroundHeights // // This function is neccessary because not all ground intersects are // loaded at any given time, due to memory considerations // // Should be called sparingly, since it needs to do ground intersects // Solution: To be Amortised internally ////////////////////////////////////////////////////////////////////////// void MissionObjective::UpdateGroundHeights( SwapArray& orPathRoute ) { for(int i=orPathRoute.mUseSize-1; i>-1; i--) { if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->PlaceOnGround(0.2f, false); ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->PlaceOnGround(0.2f, false); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void MissionObjective::UpdateLongRoadArrows( PathStruct& orPathStruct ) { SwapArray& orPathRoute = orPathStruct.mPathRoute; if( !(DirectionalArrowEnum::INTERSECTION & mArrowType) ) return; //This is a temporary hack to prevent crashes, when the list is size 1 // it will be removed as soon as this system is cleaned up to follow paths // arbitrarily instead of at the quantised road/intersection level. if( orPathRoute.mUseSize<2 ) return; RoadManager::PathElement lastPathElem; RoadSegment* pLastRoadSegment; float lastSegmentT; float lastRoadT; rmt::Vector playerPosn; GetAvatarManager()->GetAvatarForPlayer(0)->GetLastPathInfo( lastPathElem, pLastRoadSegment, lastSegmentT, lastRoadT ); GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(playerPosn); if(lastPathElem.type == RoadManager::ET_INTERSECTION) { return; } // // Determine whether the players on the path that we want to light. // for(int i=orPathRoute.mUseSize-1; i>-1; i--) { if(orPathRoute[i].type == RoadManager::ET_INTERSECTION) continue; if( (((Road*)(orPathRoute[i].elem))->GetSourceIntersection() == ((Road*)(lastPathElem.elem))->GetSourceIntersection() && ((Road*)(orPathRoute[i].elem))->GetDestinationIntersection() == ((Road*)(lastPathElem.elem))->GetDestinationIntersection()) || (((Road*)(orPathRoute[i].elem))->GetSourceIntersection() == ((Road*)(lastPathElem.elem))->GetDestinationIntersection() && ((Road*)(orPathRoute[i].elem))->GetDestinationIntersection() == ((Road*)(lastPathElem.elem))->GetSourceIntersection()) ) //found matching path { Road* pRoad = ((Road*)(orPathRoute[i].elem)); float roadLen = pRoad->GetRoadLength(); int numArrowsToPlace = static_cast< int >( ( roadLen / 40.0f ) - 1.0f ); if(numArrowsToPlace>5) numArrowsToPlace=5; if(numArrowsToPlace<0) numArrowsToPlace=0; RoadSegment* pRoadSegmentPlacement = NULL; RoadSegment* pRoadSegReference = NULL; rmt::Vector pathHeading, roadSegPlacementFacing, pathPosn, roadStartPosn, roadEndPosn, tempVect, tempVect2; float distStartToNextRoad, distEndToNextRoad, scaleFactor, distPlayerFromRoad; RoadSegment* pRoadStart = pRoad->GetRoadSegment(0); RoadSegment* pRoadEnd = pRoad->GetRoadSegment(pRoad->GetNumRoadSegments()-1); int playerRoadSegIndex = 0; pLastRoadSegment->GetPosition(&tempVect); RoadManager::FindClosestPointOnRoad( pRoad, tempVect, tempVect2, distPlayerFromRoad, playerRoadSegIndex ); // //Determine if our path lands on a road heading the wrong direction //If so, we need to invert arrow headings // pRoadEnd->GetPosition(&roadEndPosn); pRoadStart->GetPosition(&roadStartPosn); // // Yay! Another Special Case // if(pRoadEnd==pRoadStart) { pRoadStart->GetCorner(0,roadStartPosn); pRoadStart->GetCorner(1,roadEndPosn); } if(i>0) { rAssert(orPathRoute[i-1].type == RoadManager::ET_INTERSECTION); ((Intersection*)(orPathRoute[i-1].elem))->GetLocation(tempVect2); //invert distances, since we're using the previous intersection in this case tempVect.Sub(tempVect2, roadEndPosn); distStartToNextRoad = tempVect.MagnitudeSqr(); tempVect.Sub(tempVect2, roadStartPosn); distEndToNextRoad = tempVect.MagnitudeSqr(); } else { if(orPathRoute.mUseSize==1) //return for now, since there's only one road, and we don't have origin, destination info return; rAssert(orPathRoute[i+1].type == RoadManager::ET_INTERSECTION); ((Intersection*)(orPathRoute[i+1].elem))->GetLocation(tempVect2); tempVect.Sub(tempVect2, roadEndPosn); distEndToNextRoad = tempVect.MagnitudeSqr(); tempVect.Sub(tempVect2, roadStartPosn); distStartToNextRoad = tempVect.MagnitudeSqr(); } if(distStartToNextRoad0) //if we have an intersection previous { rAssert(orPathRoute[i-1].type == RoadManager::ET_INTERSECTION); ((Intersection*)(orPathRoute[i-1].elem))->AnimEntity(0)->GetAnimRootHeading(pathHeading); ((Intersection*)(orPathRoute[i-1].elem))->AnimEntity(0)->GetPosition(&pathPosn); } else { GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetAnimRootHeading(pathHeading); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetPosition(&pathPosn); } // // Find out whic part of the road we're closer to, so that we can use that // piece of road for directional reference // pRoadStart->GetPosition(0.0f,0.0f,&roadStartPosn); pRoadEnd->GetPosition( 0.0f,0.0f,&roadEndPosn); tempVect.Sub(roadStartPosn,pathPosn); distToStart = tempVect.MagnitudeSqr(); tempVect.Sub(roadEndPosn,pathPosn); distToEnd = tempVect.MagnitudeSqr(); if(distToStartGetEdgeNormal(0,tempVect); if( tempVect.Dot(pathHeading)<0.0f ) scaleFactor = -1.0f; else scaleFactor = 1.0f; */ for(int j=5; j>0; j--) { if(j<=numArrowsToPlace) { float curDistPlacement = j*40.0f; float realDistPlacement = 0.0f; pRoad->FindRoadSegmentAtDist(curDistPlacement, &pRoadSegmentPlacement); //if we're at the end of the path, cut arrows off past the goal if(pRoad == orPathStruct.mpTargetRoadSeg->GetRoad() ) { if( scaleFactor == 1.0f ) //if we're going forward on the road { if( pRoadSegmentPlacement->GetSegmentIndex() > orPathStruct.mpTargetRoadSeg->GetSegmentIndex() ) continue; } else // we're going backward on the road { if( pRoadSegmentPlacement->GetSegmentIndex() < orPathStruct.mpTargetRoadSeg->GetSegmentIndex() ) continue; } } pRoadSegmentPlacement->GetPosition(0.0f, 0.0f, &tempVect); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j], tempVect); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j], tempVect); tempVect2.Sub( playerPosn, tempVect ); distPlayerFromRoad = tempVect2.MagnitudeSqr(); //ensure it's out of view first if( distPlayerFromRoad > 120.0f && ( scaleFactor == 1.0f && ((int)pRoadSegmentPlacement->GetSegmentIndex()) < playerRoadSegIndex || scaleFactor == -1.0f && ((int)pRoadSegmentPlacement->GetSegmentIndex()) > playerRoadSegIndex) ) { //we're lighting a road piece further away from the goal than the user GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(false); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(true); } else { //we're lighting a road piece further toward the goal than the user GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(true); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(false); } //GetHeadingAlongPath(orPathRoute, i, (RoadSegment*)pRoadSegmentPlacement, tempVect); //pRoadSegmentPlacement->GetPosition(0.0f, 0.0f, &tempVect2); //tempVect.Sub( tempVect, tempVect2 ); pRoadSegmentPlacement->GetEdgeNormal(0,tempVect); tempVect.Scale(scaleFactor); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetAnimRootHeadingYUp( tempVect ); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetAnimRootHeadingYUp( tempVect ); /* if( pRoadSegmentPlacement != NULL ) { pRoadSegmentPlacement->GetPosition(0.0f, 0.0f, &tempVect); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j], tempVect); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j], tempVect); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(true); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(false); pRoadSegmentPlacement->GetEdgeNormal(0,tempVect); tempVect.Scale(scaleFactor); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetAnimRootHeadingYUp( tempVect ); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetAnimRootHeadingYUp( tempVect ); } else { rAssert(false); } */ } else { tempVect.Set(0.0f,0.0f,0.0f); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j], tempVect); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j], tempVect); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(false); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(false); } } i=-1; } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// bool MissionObjective::FindNearestRoadIconAhead ( SwapArray& orPathRoute, rmt::Vector& irPosn, rmt::Vector& orIconPosn, rmt::Vector& orIconFacing ) { float nearestInter = 36000000.0f;//6000.0f*6000.0f; float temp; rmt::Vector tempPosn; bool retVal = false; int i; if( DirectionalArrowEnum::INTERSECTION & mArrowType ) { // // Go through the intersections in the path, finding the nearest // for(i=orPathRoute.mUseSize-1; i>-1; i--) { if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->GetLocation(orIconPosn); tempPosn.Sub(orIconPosn,irPosn); temp = tempPosn.MagnitudeSqr(); if( temp < nearestInter ) { nearestInter = temp; ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->GetAnimRootHeading(orIconFacing); } } } // // Go through the active right way markers, finding the nearest // for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>0; i--) { if(!GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->GetVisibility()) continue; GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->GetPosition(&orIconPosn); tempPosn.Sub(orIconPosn,irPosn); temp = tempPosn.MagnitudeSqr(); if( temp < nearestInter ) { nearestInter = temp; GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->GetAnimRootHeading(orIconFacing); } } // // Go through the active wrong way markers, finding the nearest // for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>0; i--) { if(!GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->GetVisibility()) continue; GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->GetPosition(&orIconPosn); tempPosn.Sub(orIconPosn,irPosn); temp = tempPosn.MagnitudeSqr(); if( temp < nearestInter ) { nearestInter = temp; GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->GetAnimRootHeading(orIconFacing); } } } if( DirectionalArrowEnum::NEAREST_ROAD & mArrowType ) { GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetPosition(&orIconPosn); tempPosn.Sub(orIconPosn,irPosn); temp = tempPosn.MagnitudeSqr(); if( temp < nearestInter ) { nearestInter = temp; GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetAnimRootHeading(orIconFacing); } } if(nearestInter<36000000.0f) retVal = true; return retVal; } ////////////////////////////////////////////////////////////////////////// void MissionObjective::LightPath ( rmt::Vector& irTargetPosn, PathStruct& orPathStruct ) { if( DirectionalArrowEnum::NEITHER & mArrowType ) return; orPathStruct.mUpdateCount=0; //initialize the update for modulo updates (so we dont update arrows on ground height per frame) SwapArray& orPathRoute = orPathStruct.mPathRoute; // rReleasePrintf("LightPath. 0x%x\n", orPathRoute.mpData ); RoadSegment* pSourceRoadSeg = NULL; RoadSegment* pTargetRoadSeg = NULL; rmt::Vector sourcePosn, targetPosn, closestPosn; float SourceTVal, TargetTVal; if( orPathRoute.mUseSize != 0 ) { //this shouldn't happen but we are going to ignore it. rTuneAssert(0); return; } if( GetInteriorManager()->IsInside() ) { //Check for an all-interior mission, in which case, //forget lighting entirely GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(sourcePosn); sourcePosn.Sub(sourcePosn,irTargetPosn); //I'm assured that the interiors ar <100m in size and >=200m from the rest of the world if(sourcePosn.MagnitudeSqr()< 10000.0f) return; GetInteriorManager()->ExteriorCharPosn(sourcePosn); } else { GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(sourcePosn); } ////////////////////////////////////////////////////////////////////////// // If Target is in an interior, and source is not, we want to get // the target's exterior posn ////////////////////////////////////////////////////////////////////////// tName interiorName = GetInteriorManager()->ClassifyPoint( irTargetPosn ); float dummy; if(interiorName.GetUID()!= static_cast< tUID >( 0 ) ) { ZoneEventLocator* pZEL = p3d::find(interiorName.GetUID()); pZEL->GetPosition(&targetPosn); GetIntersectManager()->FindClosestRoad(targetPosn, 50.0f, pTargetRoadSeg, dummy ); } else { targetPosn = irTargetPosn; } GetIntersectManager()->FindClosestRoad(targetPosn, 50.0f, pTargetRoadSeg, dummy ); rAssert( pTargetRoadSeg != NULL ); GetIntersectManager()->FindClosestRoad(sourcePosn, 50.0f, pSourceRoadSeg, dummy ); rAssert( pSourceRoadSeg != NULL ); RoadManager::PathElement sourcePath, targetPath; if( pSourceRoadSeg != NULL ) sourcePath.elem = pSourceRoadSeg->GetRoad(); sourcePath.type = RoadManager::ET_NORMALROAD; if( pTargetRoadSeg != NULL ) targetPath.elem = pTargetRoadSeg->GetRoad(); targetPath.type = RoadManager::ET_NORMALROAD; ////////////////////////////////////////////////////////////////////////// // Determine Source and Target T Values ////////////////////////////////////////////////////////////////////////// RoadManager* pRoadManager = RoadManager::GetInstance(); float closestDist; int closestSegIndex; pRoadManager->FindClosestPointOnRoad( (Road*)sourcePath.elem, sourcePosn, closestPosn, closestDist, closestSegIndex ); SourceTVal = pRoadManager->DetermineRoadT( pSourceRoadSeg, pRoadManager->DetermineSegmentT( closestPosn, pSourceRoadSeg ) ); pRoadManager->FindClosestPointOnRoad( (Road*)targetPath.elem, targetPosn, closestPosn, closestDist, closestSegIndex ); TargetTVal = pRoadManager->DetermineRoadT( pTargetRoadSeg, pRoadManager->DetermineSegmentT( closestPosn, pTargetRoadSeg ) ); ////////////////////////////////////////////////////////////////////////// // Find Path ////////////////////////////////////////////////////////////////////////// if( pTargetRoadSeg != NULL && pSourceRoadSeg != NULL ) { RoadManager::GetInstance()->FindPathElementsBetween( false, sourcePath, SourceTVal, sourcePosn, targetPath, TargetTVal, targetPosn, orPathRoute ); } else { rAssert(false); //we should always have nav info for this } #ifdef RAD_DEBUG pSourceRoadSeg->GetPosition( &mPathStart ); pTargetRoadSeg->GetPosition( &mPathEnd ); #endif orPathStruct.mpTargetRoadSeg = pTargetRoadSeg; orPathStruct.mTargetPosn = targetPosn; AnimEntityDSG* pAnimEDSG; AnimEntityDSG* pWrongwayAnimDSG; rmt::Vector pathHeading; rmt::Vector pathTemp; int i; if( DirectionalArrowEnum::INTERSECTION & mArrowType ) { for( i=orPathRoute.mUseSize-1; i>-1; i-- ) { //Set visibility and align arrows for path highlighting if( orPathRoute[i].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i].elem))->GetLocation(sourcePosn); pWrongwayAnimDSG = ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1); pAnimEDSG = ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0); pAnimEDSG->SetVisibility(true); if( i+2 < orPathRoute.mUseSize ) //There's definitely some(other intersection) beyond this intersection { if( orPathRoute[i+1].type == RoadManager::ET_INTERSECTION ) { ((Intersection*)(orPathRoute[i+1].elem))->GetLocation(pathHeading); } else { ((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading); ((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(((Road*)(orPathRoute[i+1].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp); if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() ) { pathHeading = pathTemp; } } } else //No(other intersection) beyond this intersection { //Alpha semi-hack: Doing this because intersections aren't as easy //to find because they're not in the tree. So, only do direct //point if intersection is closer than the nearest road seg. float intersectionToTarget = (targetPosn - sourcePosn).MagnitudeSqr(); ((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading); ((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(((Road*)(orPathRoute[i+1].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp); if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() ) { pathHeading = pathTemp; } if( //intersectionToTarget < (targetPosn - pathHeading).MagnitudeSqr() || intersectionToTarget < 1600.0f ) { pathHeading = targetPosn; } /* if( (targetPosn - sourcePosn).MagnitudeSqr() < 900.0f) { pathHeading = targetPosn; } else { ((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading); ((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(((Road*)(orPathRoute[i+1].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp); if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() ) { pathHeading = pathTemp; } } */ } pathHeading.Sub( pathHeading, sourcePosn ); //pAnimEDSG->PlaceOnGround( 0.2f ); pAnimEDSG->SetAnimRootHeadingYUp( pathHeading ); pWrongwayAnimDSG->SetAnimRootHeadingYUp( pathHeading ); } } } ////////////////////////////////////////////////////////////////////////// //move the floating arrow to the correct place ////////////////////////////////////////////////////////////////////////// pSourceRoadSeg->GetPosition(0.0f, 0.0f, &sourcePosn); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0], sourcePosn); UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0], sourcePosn); if( DirectionalArrowEnum::NEAREST_ROAD & mArrowType ) { /* rmt::Box3D oldBBox; GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetBoundingBox( &oldBBox ); pSourceRoadSeg->GetPosition(0.0f, 0.0f, &sourcePosn); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetPosition( sourcePosn ); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->PlaceOnGround( 0.2f ); GetRenderManager()->pWorldScene()->Move(oldBBox, GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->GetBoundingBox( &oldBBox ); pSourceRoadSeg->GetPosition(0.0f, 0.0f, &sourcePosn); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetPosition( sourcePosn ); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->PlaceOnGround( 0.2f ); GetRenderManager()->pWorldScene()->Move(oldBBox, GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]); */ GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(true); i = 0; if(i+1GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading); ((Road*)(orPathRoute[i].elem))->GetRoadSegment(((Road*)(orPathRoute[i].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp); if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() ) { pathHeading = pathTemp; } } } else //Nothing in this path { pathHeading = targetPosn; } pathHeading.Sub( pathHeading, sourcePosn ); GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetAnimRootHeadingYUp( pathHeading ); GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetAnimRootHeadingYUp( pathHeading ); } if(!GetCharacterSheetManager()->QueryNavSystemSetting()) { UnlightCurrentPath(orPathRoute); return; } } ////////////////////////////////////////////////////////////////////////// void MissionObjective::GetHeadingAlongPath ( SwapArray& irPathRoute, int i, RoadSegment* ipSourceRoadSeg, rmt::Vector& orPathHeading ) { // bool invertResults; // rmt::Vector pathTemp2, pathTemp; rmt::Vector tempVect, tempVect2; rmt::Vector roadEndPosn, roadStartPosn; float distStartToNextRoad, distEndToNextRoad, scaleFactor; RoadSegment* pRoadStart = ipSourceRoadSeg->GetRoad()->GetRoadSegment(0); RoadSegment* pRoadEnd = ipSourceRoadSeg->GetRoad()->GetRoadSegment(ipSourceRoadSeg->GetRoad()->GetNumRoadSegments()-1); // // Yay! Another Special Case // if(pRoadEnd==pRoadStart) { pRoadStart->GetCorner(0,roadStartPosn); pRoadStart->GetCorner(1,roadEndPosn); } else { pRoadStart->GetPosition( &roadStartPosn ); pRoadEnd->GetPosition( &roadEndPosn ); } if(i>0) { rAssert(irPathRoute[i-1].type == RoadManager::ET_INTERSECTION); ((Intersection*)(irPathRoute[i-1].elem))->GetLocation(tempVect2); //invert distances, since we're using the previous intersection in this case tempVect.Sub(tempVect2, roadEndPosn); distStartToNextRoad = tempVect.MagnitudeSqr(); tempVect.Sub(tempVect2, roadStartPosn); distEndToNextRoad = tempVect.MagnitudeSqr(); } else { if(irPathRoute.mUseSize==1) //return for now, since there's only one road, and we don't have origin, destination info return; rAssert(irPathRoute[i+1].type == RoadManager::ET_INTERSECTION); ((Intersection*)(irPathRoute[i+1].elem))->GetLocation(tempVect2); tempVect.Sub(tempVect2, roadEndPosn); distEndToNextRoad = tempVect.MagnitudeSqr(); tempVect.Sub(tempVect2, roadStartPosn); distStartToNextRoad = tempVect.MagnitudeSqr(); } if(distStartToNextRoadGetEdgeNormal(0,orPathHeading); orPathHeading.Scale(scaleFactor); ipSourceRoadSeg->GetPosition(0.0f, 0.0f, &tempVect); orPathHeading.Add(tempVect); /* if(i+1 < irPath.mUseSize) { ((Intersection*)(irPath[i+1].elem))->GetLocation(orPathHeading); if(((Intersection*)(irPath[i+1].elem)) == ipSourceRoadSeg->GetRoad()->GetSourceIntersection()) invertResults=true; else invertResults=false; } else { ((Intersection*)(irPath[i-1].elem))->GetLocation(orPathHeading); if(((Intersection*)(irPath[i-1].elem)) == ipSourceRoadSeg->GetRoad()->GetSourceIntersection()) invertResults=true; else invertResults=false; } if(ipSourceRoadSeg->GetSegmentIndex()+1 > ((Road*)(irPath[i].elem))->GetNumRoadSegments()-1) ipSourceRoadSeg->GetPosition(0.0f,0.0f,&pathTemp); else ((Road*)(irPath[i].elem))->GetRoadSegment(ipSourceRoadSeg->GetSegmentIndex()+1)->GetPosition(0.0f,0.0f,&pathTemp); float roadToIntersection1 = (orPathHeading - pathTemp).MagnitudeSqr(); if(ipSourceRoadSeg->GetSegmentIndex() == 0) ipSourceRoadSeg->GetPosition(0.0f,0.0f,&pathTemp2); else ((Road*)(irPath[i].elem))->GetRoadSegment(ipSourceRoadSeg->GetSegmentIndex()-1)->GetPosition(0.0f,0.0f,&pathTemp2); float roadToIntersection2 = (orPathHeading - pathTemp2).MagnitudeSqr(); if( roadToIntersection1 < roadToIntersection2 && !invertResults ) { orPathHeading = pathTemp; } else { orPathHeading = pathTemp2; }*/ } ////////////////////////////////////////////////////////////////////////// void MissionObjective::UpdateAnimPosition( AnimEntityDSG* pAnimEntityDSG, rmt::Vector& irPosn ) { rmt::Box3D oldBBox; pAnimEntityDSG->GetBoundingBox( &oldBBox ); pAnimEntityDSG->SetPosition( irPosn ); pAnimEntityDSG->PlaceOnGround( 0.2f, false ); GetRenderManager()->pWorldScene()->Move(oldBBox, pAnimEntityDSG ); } //============================================================================= // MissionObjective::IsPattyAndSelmaDialog //============================================================================= // Description: determines if this is a patty and selma dialog objective // // Parameters: NONE // // Return: true/false - is this patty and selma talking to one another? // //============================================================================= bool MissionObjective::IsPattyAndSelmaDialog() const { unsigned int i = 0; for( ; i < mNumNPCs; ++i ) { if( strcmp( mNPCNames[ i ], "patty" ) == 0 ) { return true; } if( strcmp( mNPCNames[ i ], "zmale1" ) == 0 ) { return true; } if( strcmp( mNPCNames[ i ], "zmale2" ) == 0 ) { return true; } if( strcmp( mNPCNames[ i ], "zmale3" ) == 0 ) { return true; } } return false; } //============================================================================= // MissionObjective::IsRaceDialog //============================================================================= // Description: in a race dialog, you will be talking to milhouse, ralph, or // nelson // // Parameters: NONE // // Return: true/false - is this one of the race characters we're talking // to // //============================================================================= bool MissionObjective::IsRaceDialog() const { unsigned int i = 0; for( ; i < mNumNPCs; ++i ) { if( strcmp( mNPCNames[ i ], "milhouse" ) == 0 ) { return true; } if( strcmp( mNPCNames[ i ], "ralph" ) == 0 ) { return true; } if( strcmp( mNPCNames[ i ], "nelson" ) == 0 ) { return true; } } return false; }