/* ============ idAASLocal::DrawReachability ============ */ void idAASLocal::DrawReachability( const idReachability *reach ) const { idVec4 reachColor = colorCyan; if (reach->travelType & TFL_DOOR) { reachColor = colorRed; } gameRenderWorld->DebugArrow( reachColor, reach->start, reach->end, 1, 10000 ); gameRenderWorld->DebugArrow( colorLtGrey, AreaCenter(reach->fromAreaNum), AreaCenter(reach->toAreaNum), 1, 10000); if ( gameLocal.GetLocalPlayer() ) { gameRenderWorld->DrawText( va( "%d", reach->edgeNum ), ( reach->start + reach->end ) * 0.5f, 0.1f, colorWhite, gameLocal.GetLocalPlayer()->viewAxis, 1, 10000 ); } switch( reach->travelType ) { case TFL_WALK: { // const idReachability_Walk *walk = static_cast<const idReachability_Walk *>(reach); break; } default: { break; } } }
/* ============ idAASLocal::Test ============ */ void idAASLocal::Test( const idVec3 &origin ) { if ( !file ) { return; } if ( aas_randomPullPlayer.GetBool() ) { RandomPullPlayer( origin ); } if ( ( aas_pullPlayer.GetInteger() > 0 ) && ( aas_pullPlayer.GetInteger() < file->GetNumAreas() ) ) { ShowWalkPath( origin, aas_pullPlayer.GetInteger(), AreaCenter( aas_pullPlayer.GetInteger() ) ); PullPlayer( origin, aas_pullPlayer.GetInteger() ); } if ( ( aas_showPath.GetInteger() > 0 ) && ( aas_showPath.GetInteger() < file->GetNumAreas() ) ) { ShowWalkPath( origin, aas_showPath.GetInteger(), AreaCenter( aas_showPath.GetInteger() ) ); } if ( ( aas_showFlyPath.GetInteger() > 0 ) && ( aas_showFlyPath.GetInteger() < file->GetNumAreas() ) ) { ShowFlyPath( origin, aas_showFlyPath.GetInteger(), AreaCenter( aas_showFlyPath.GetInteger() ) ); } if ( ( aas_showHideArea.GetInteger() > 0 ) && ( aas_showHideArea.GetInteger() < file->GetNumAreas() ) ) { ShowHideArea( origin, aas_showHideArea.GetInteger() ); } if ( aas_showAreas.GetBool() ) { ShowArea( origin ); } if ( aas_showWallEdges.GetBool() ) { ShowWallEdges( origin ); } if ( aas_showPushIntoArea.GetBool() ) { ShowPushIntoArea( origin ); } }
/* ============ idAASFileLocal::AreaReachableGoal ============ */ idVec3 idAASFileLocal::AreaReachableGoal( int areaNum ) const { int i, faceNum, numFaces; const aasArea_t *area; idVec3 center; idVec3 start, end; aasTrace_t trace; area = &areas[areaNum]; if ( !(area->flags & (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY)) || (area->flags & AREA_LIQUID) ) { return AreaCenter( areaNum ); } center = vec3_origin; numFaces = 0; for ( i = 0; i < area->numFaces; i++ ) { faceNum = faceIndex[area->firstFace + i]; if ( !(faces[abs(faceNum)].flags & FACE_FLOOR) ) { continue; } center += FaceCenter( abs(faceNum) ); numFaces++; } if ( numFaces > 0 ) { center /= numFaces; } center[2] += 1.0f; end = center; end[2] -= 1024; Trace( trace, center, end ); return trace.endpos; }
/* ============ idAASLocal::DrawArea ============ */ void idAASLocal::DrawArea( int areaNum ) const { int i, j, numEdges, firstEdge; idVec3 mid, end; const aasArea_t *area; const aasReachability_t *reach; if ( !file ) { return; } area = &file->GetArea( areaNum ); numEdges = area->numEdges; firstEdge = area->firstEdge; mid.Zero(); for ( i = 0; i < numEdges; i++ ) { DrawEdge( abs( file->GetEdgeIndex( firstEdge + i ) ), true ); j = file->GetEdgeIndex( firstEdge + i ); mid += file->GetVertex( file->GetEdge( abs( j ) ).vertexNum[ j < 0 ] ); } mid /= numEdges; end = mid + 5.0f * file->GetSettings().invGravityDir; gameRenderWorld->DebugArrow( colorGreen, mid, end, 1, 0 ); for ( reach = area->reach; reach; reach = reach->next ) { DrawReachability( reach, NULL ); } gameRenderWorld->DrawText( va( "%d", areaNum ), AreaCenter( areaNum ) + idVec3( 0.0f, 0.0f, 4.0f ), 0.1f, colorWhite, gameLocal.GetLocalPlayer()->GetViewAxis(), 1, 0 ); }
/* ============ idAASLocal::PullPlayer ============ */ bool idAASLocal::PullPlayer( const idVec3& origin, int toAreaNum ) const { int areaNum; idVec3 areaCenter, dir, vel; idAngles delta; aasPath_t path; idPlayer* player; player = gameLocal.GetLocalPlayer(); if( !player ) { return true; } idPhysics* physics = player->GetPhysics(); if( !physics ) { return true; } if( !toAreaNum ) { return false; } areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), ( AREA_REACHABLE_WALK | AREA_REACHABLE_FLY ) ); areaCenter = AreaCenter( toAreaNum ); if( player->GetPhysics()->GetAbsBounds().Expand( 8 ).ContainsPoint( areaCenter ) ) { return false; } if( WalkPathToGoal( path, areaNum, origin, toAreaNum, areaCenter, TFL_WALK | TFL_AIR ) ) { dir = path.moveGoal - origin; dir[2] *= 0.5f; dir.Normalize(); delta = dir.ToAngles() - player->cmdAngles - player->GetDeltaViewAngles(); delta.Normalize180(); player->SetDeltaViewAngles( player->GetDeltaViewAngles() + delta * 0.1f ); dir[2] = 0.0f; dir.Normalize(); dir *= 100.0f; vel = physics->GetLinearVelocity(); dir[2] = vel[2]; physics->SetLinearVelocity( dir ); return true; } else { return false; } }
/* ============ idAASLocal::RandomPullPlayer ============ */ void idAASLocal::RandomPullPlayer( const idVec3 &origin ) const { int rnd, i, n; if( !PullPlayer( origin, aas_pullPlayer.GetInteger() ) ) { rnd = gameLocal.random.RandomFloat() * file->GetNumAreas(); for( i = 0; i < file->GetNumAreas(); i++ ) { n = ( rnd + i ) % file->GetNumAreas(); if( file->GetArea( n ).flags & ( AREA_REACHABLE_WALK | AREA_REACHABLE_FLY ) ) { aas_pullPlayer.SetInteger( n ); } } } else { ShowWalkPath( origin, aas_pullPlayer.GetInteger(), AreaCenter( aas_pullPlayer.GetInteger() ) ); } }
/* ============ idAASLocal::ShowNearestCoverArea ============ */ void idAASLocal::ShowNearestCoverArea( const idVec3 &origin, int targetAreaNum ) const { int areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), AAS_AREA_REACHABLE_WALK, TravelFlagInvalidForTeam() ); idVec3 target = AreaCenter( targetAreaNum ); DrawCone( target, idVec3(0,0,1), 16.0f, colorYellow ); idAASCallback_FindCoverArea findCover( target ); idAASGoal goal; if ( FindNearestGoal( goal, areaNum, origin, TravelFlagInvalidForTeam(), findCover ) ) { DrawArea( goal.areaNum ); ShowWalkPath( areaNum, origin, goal.areaNum, goal.origin, TravelFlagForTeam(), TravelFlagWalkForTeam() ); DrawCone( goal.origin, idVec3( 0, 0, 1 ), 16.0f, colorWhite ); } }
/* ============ idAASLocal::ShowHideArea ============ */ void idAASLocal::ShowHideArea( const idVec3 &origin, int targetAreaNum ) const { int areaNum, numObstacles; idVec3 target; aasGoal_t goal; aasObstacle_t obstacles[10]; areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), ( AREA_REACHABLE_WALK | AREA_REACHABLE_FLY ) ); target = AreaCenter( targetAreaNum ); // consider the target an obstacle obstacles[0].absBounds = idBounds( target ).Expand( 16 ); numObstacles = 1; DrawCone( target, idVec3( 0, 0, 1 ), 16.0f, colorYellow ); idAASFindCover findCover( target ); if( FindNearestGoal( goal, areaNum, origin, target, TFL_WALK | TFL_AIR, obstacles, numObstacles, findCover ) ) { DrawArea( goal.areaNum ); ShowWalkPath( origin, goal.areaNum, goal.origin ); DrawCone( goal.origin, idVec3( 0, 0, 1 ), 16.0f, colorWhite ); } }
/* ============ idAASLocal::RandomPullPlayer ============ */ void idAASLocal::RandomPullPlayer( const idVec3 &origin, int mode ) const { int areaNum, travelTime; static int bestTravelTime = 0; static int startAreaNum = 0; static int goalAreaNum = 0; static int failedCount; if ( goalAreaNum > file->GetNumAreas() ) { goalAreaNum = 0; } if ( !PullPlayer( origin, goalAreaNum, AreaCenter( goalAreaNum ), areaNum, travelTime ) ) { startAreaNum = 0; bestTravelTime = INT_MAX; int rnd = idMath::Ftoi( gameLocal.random.RandomFloat() * file->GetNumAreas() ); for ( int i = 0; i < file->GetNumAreas(); i++ ) { int n = ( rnd + i ) % file->GetNumAreas(); if ( ( file->GetArea( n ).flags & AAS_AREA_REACHABLE_WALK ) != 0 ) { goalAreaNum = n; } } } else if ( startAreaNum == 0 ) { startAreaNum = areaNum; bestTravelTime = travelTime; } if ( travelTime < bestTravelTime ) { bestTravelTime = travelTime; failedCount = 0; } else { failedCount++; } if ( failedCount > 10 * 1000 / USERCMD_MSEC ) { failedCount = 0; if ( mode > 1 ) { common->Warning( "failed to go from area %d to area %d at area %d", startAreaNum, goalAreaNum, areaNum ); goalAreaNum = 0; } } }
/* ============ idAASLocal::GetAreaNumAndLocation ============ */ bool idAASLocal::GetAreaNumAndLocation( idCVar &cvar, const idVec3 &origin, int &areaNum, idVec3 &location ) const { areaNum = 0; location.Zero(); if ( cvar.GetString()[0] == '\0' ) { return false; } if ( idStr::Icmp( cvar.GetString(), "memory" ) == 0 ) { cvar.SetString( aas_locationMemory.GetString() ); } if ( idStr::Icmp( cvar.GetString(), "current" ) == 0 ) { cvar.SetString( origin.ToString() ); } idLexer src( LEXFL_NOERRORS|LEXFL_NOWARNINGS ); src.LoadMemory( cvar.GetString(), idStr::Length( cvar.GetString() ), "areaNum" ); bool error = false; location.x = src.ParseFloat( &error ); location.y = src.ParseFloat( &error ); location.z = src.ParseFloat( &error ); if ( !error ) { areaNum = PointReachableAreaNum( location, DefaultSearchBounds(), AAS_AREA_REACHABLE_WALK, TravelFlagInvalidForTeam() ); PushPointIntoArea( areaNum, location ); return true; } src.Reset(); areaNum = src.ParseInt(); if ( ( areaNum > 0 ) && ( areaNum < file->GetNumAreas() ) ) { location = AreaCenter( areaNum ); return true; } return false; }
void idAASLocal::DrawAreas(const idVec3& playerOrigin) { if ( file == NULL ) { return; } // Initialize AAS area colors if we haven't already done so if ( aasColors.Num() == 0 ) { // Get a color for each cluster int numClusters = file->GetNumClusters(); for ( int c = 0 ; c < numClusters ; c++ ) { aasColors.Alloc() = idVec4(gameLocal.random.RandomFloat() + 0.1f, gameLocal.random.RandomFloat() + 0.1f, gameLocal.random.RandomFloat() + 0.1f, 1); } } idMat3 playerViewMatrix(gameLocal.GetLocalPlayer()->viewAngles.ToMat3()); idList<int> clusterNums; // Paint the AAS areas for ( int i = 0 ; i < file->GetNumAreas() ; i++ ) { idVec3 areaCenter = AreaCenter(i); // angua: only draw areas near the player, no need to see them at the other end of the map if ( (areaCenter - playerOrigin).LengthFast() < 150 ) { idBounds areaBounds = GetAreaBounds(i); int clusterNum = file->GetArea(i).cluster; clusterNums.AddUnique(clusterNum); idVec4 color = (clusterNum <= 0) ? colorWhite : aasColors[clusterNum]; gameRenderWorld->DrawText(va("%d", i), areaCenter, 0.2f, color, playerViewMatrix, 1, 16); gameRenderWorld->DebugBox(color, idBox(areaBounds), 16); } } // Paint the cluster numbers for ( int i = 0 ; i < clusterNums.Num() ; i++ ) { int area = GetAreaInCluster(clusterNums[i]); if ( area <= 0 ) { continue; } idVec3 origin = file->GetArea(area).center; if ( (origin - playerOrigin).LengthFast() < 300 ) { gameRenderWorld->DrawText(va("%d", clusterNums[i]), origin, 1, colorRed, playerViewMatrix, 1, 16); } } }