/* ============ idAASLocal::ShowArea ============ */ void idAASLocal::ShowArea(const idVec3 &origin) const { static int lastAreaNum; int areaNum; const aasArea_t *area; idVec3 org; areaNum = PointReachableAreaNum(origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY)); org = origin; PushPointIntoAreaNum(areaNum, org); if (aas_goalArea.GetInteger()) { int travelTime; idReachability *reach; RouteToGoalArea(areaNum, org, aas_goalArea.GetInteger(), TFL_WALK|TFL_AIR, travelTime, &reach); gameLocal.Printf("\rtt = %4d", travelTime); if (reach) { gameLocal.Printf(" to area %4d", reach->toAreaNum); DrawArea(reach->toAreaNum); } } if (areaNum != lastAreaNum) { area = &file->GetArea(areaNum); gameLocal.Printf("area %d: ", areaNum); if (area->flags & AREA_LEDGE) { gameLocal.Printf("AREA_LEDGE "); } if (area->flags & AREA_REACHABLE_WALK) { gameLocal.Printf("AREA_REACHABLE_WALK "); } if (area->flags & AREA_REACHABLE_FLY) { gameLocal.Printf("AREA_REACHABLE_FLY "); } if (area->contents & AREACONTENTS_CLUSTERPORTAL) { gameLocal.Printf("AREACONTENTS_CLUSTERPORTAL "); } if (area->contents & AREACONTENTS_OBSTACLE) { gameLocal.Printf("AREACONTENTS_OBSTACLE "); } gameLocal.Printf("\n"); lastAreaNum = areaNum; } if (org != origin) { idBounds bnds = file->GetSettings().boundingBoxes[ 0 ]; bnds[ 1 ].z = bnds[ 0 ].z; gameRenderWorld->DebugBounds(colorYellow, bnds, org); } DrawArea(areaNum); }
/* ============ idAASLocal::ShowFlyPath ============ */ void idAASLocal::ShowFlyPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const { int i, areaNum, curAreaNum, travelTime; idReachability *reach; idVec3 org, areaCenter; aasPath_t path; if( !file ) { return; } org = origin; areaNum = PointReachableAreaNum( org, DefaultSearchBounds(), AREA_REACHABLE_FLY ); PushPointIntoAreaNum( areaNum, org ); curAreaNum = areaNum; for( i = 0; i < 100; i++ ) { if( !RouteToGoalArea( curAreaNum, org, goalAreaNum, TFL_WALK | TFL_FLY | TFL_AIR, travelTime, &reach ) ) { break; } if( !reach ) { break; } gameRenderWorld->DebugArrow( colorPurple, org, reach->start, 2 ); DrawReachability( reach ); if( reach->toAreaNum == goalAreaNum ) { break; } curAreaNum = reach->toAreaNum; org = reach->end; } if( FlyPathToGoal( path, areaNum, origin, goalAreaNum, goalOrigin, TFL_WALK | TFL_FLY | TFL_AIR ) ) { gameRenderWorld->DebugArrow( colorBlue, origin, path.moveGoal, 2 ); } }
/* ============ idAASLocal::ShowWalkPath ============ */ void idAASLocal::ShowWalkPath( int startAreaNum, const idVec3 &startOrigin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, int walkTravelFlags ) const { if ( file == NULL ) { return; } int curAreaNum = startAreaNum; idVec3 org = startOrigin; for ( int i = 0; i < 100; i++ ) { int travelTime; const aasReachability_t *reach; if ( !RouteToGoalArea( curAreaNum, org, goalAreaNum, travelFlags, travelTime, &reach ) ) { break; } if ( !reach ) { break; } gameRenderWorld->DebugArrow( colorGreen, org, reach->GetStart(), 2, 0 ); DrawReachability( reach, NULL ); if ( aas_showAreas.GetBool() ) { DrawArea( curAreaNum ); } if ( reach->toAreaNum == goalAreaNum ) { break; } curAreaNum = reach->toAreaNum; org = reach->GetEnd(); } idAASPath path; if ( !WalkPathToGoal( path, startAreaNum, startOrigin, goalAreaNum, goalOrigin, travelFlags, walkTravelFlags ) ) { return; } gameRenderWorld->DebugArrow( colorBlue, startOrigin, path.moveGoal, 2, 0 ); // idObstacleAvoidance::obstaclePath_t obstaclePath; // idObstacleAvoidance obstacleAvoidance; // botThreadData.BuildObstacleList( obstacleAvoidance, startOrigin, startAreaNum, false ); // obstacleAvoidance.FindPathAroundObstacles( file->GetSettings().boundingBox, file->GetSettings().obstaclePVSRadius, this, startOrigin, path.moveGoal, obstaclePath ); // if ( obstaclePath.firstObstacle != idObstacleAvoidance::OBSTACLE_ID_INVALID ) { // path.moveGoal = obstaclePath.seekPos; // gameRenderWorld->DebugArrow( colorOrange, startOrigin, path.moveGoal, 2, 0 ); // } }
/* ============ idAASLocal::ShowHopPath ============ */ void idAASLocal::ShowHopPath( int startAreaNum, const idVec3 &startOrigin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, int walkTravelFlags, const idAASHopPathParms &parms ) const { if ( file == NULL ) { return; } int curAreaNum = startAreaNum; idVec3 org = startOrigin; for ( int i = 0; i < 100; i++ ) { int travelTime; const aasReachability_t *reach; if ( !RouteToGoalArea( curAreaNum, org, goalAreaNum, travelFlags, travelTime, &reach ) ) { break; } if ( !reach ) { break; } gameRenderWorld->DebugArrow( colorGreen, org, reach->GetStart(), 2, 0 ); DrawReachability( reach, NULL ); if ( aas_showAreas.GetBool() ) { DrawArea( curAreaNum ); } if ( reach->toAreaNum == goalAreaNum ) { break; } curAreaNum = reach->toAreaNum; org = reach->GetEnd(); } idAASPath path; if ( WalkPathToGoal( path, startAreaNum, startOrigin, goalAreaNum, goalOrigin, travelFlags, walkTravelFlags ) ) { gameRenderWorld->DebugArrow( colorBlue, startOrigin, path.moveGoal, 2 ); if ( ExtendHopPathToGoal( path, startAreaNum, startOrigin, goalAreaNum, goalOrigin, travelFlags, walkTravelFlags, parms ) ) { gameRenderWorld->DebugArrow( colorCyan, startOrigin, path.moveGoal, 2 ); } } }
/* ============ idAASLocal::PullPlayer ============ */ bool idAASLocal::PullPlayer( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int &startAreaNum, int &travelTime ) const { startAreaNum = 0; travelTime = 0; idPlayer *player = gameLocal.GetLocalPlayer(); if ( player == NULL ) { return true; } if ( goalAreaNum == 0 ) { return false; } if ( player->GetNoClip() ) { player->aasPullPlayer = false; return false; } idVec3 dir = goalOrigin - origin; float height = idMath::Fabs( dir.z ); float dist = dir.ToVec2().Length(); if ( dist < 32.0f && height < 128.0f ) { return false; } idVec3 org = origin; startAreaNum = PointReachableAreaNum( org, DefaultSearchBounds(), AAS_AREA_REACHABLE_WALK, TravelFlagInvalidForTeam() ); PushPointIntoArea( startAreaNum, org ); const aasReachability_t *reach; RouteToGoalArea( startAreaNum, org, goalAreaNum, TravelFlagForTeam(), travelTime, &reach ); ShowWalkPath( startAreaNum, org, goalAreaNum, goalOrigin, TravelFlagForTeam(), TravelFlagWalkForTeam() ); idAASPath path; if ( !WalkPathToGoal( path, startAreaNum, org, goalAreaNum, goalOrigin, TravelFlagForTeam(), TravelFlagWalkForTeam() ) ) { return false; } idObstacleAvoidance::obstaclePath_t obstaclePath; idObstacleAvoidance obstacleAvoidance; botThreadData.BuildObstacleList( obstacleAvoidance, org, startAreaNum, false ); obstacleAvoidance.FindPathAroundObstacles( file->GetSettings().boundingBox, file->GetSettings().obstaclePVSRadius, this, org, path.moveGoal, obstaclePath ); path.moveGoal = obstaclePath.seekPos; player->aasPullPlayer = true; usercmd_t usercmd; memset( &usercmd, 0, sizeof( usercmd ) ); usercmd.forwardmove = 127; usercmd.buttons.btn.run = true; usercmd.buttons.btn.sprint = false; idVec3 moveDir = path.moveGoal - org; idVec3 horizontalDir( moveDir.x, moveDir.y, 0.0f ); float horizontalDist = horizontalDir.Normalize(); moveDir.Normalize(); switch( path.type ) { case PATHTYPE_WALKOFFLEDGE: case PATHTYPE_WALKOFFBARRIER: { if ( horizontalDist < 80.0f ) { usercmd.buttons.btn.run = false; usercmd.forwardmove = 16 + horizontalDist; } break; } case PATHTYPE_BARRIERJUMP: case PATHTYPE_JUMP: { if ( horizontalDist < 24.0f ) { pullPlayerState.jumpNow = !pullPlayerState.jumpNow; if ( pullPlayerState.jumpNow ) { usercmd.upmove = 127; } } if ( player->GetPlayerPhysics().IsGrounded() ) { if ( horizontalDist < 100.0f ) { usercmd.buttons.btn.run = false; usercmd.forwardmove = 8 + horizontalDist; } } else { moveDir = path.reachability->GetEnd() - org; moveDir.Normalize(); } break; } case PATHTYPE_LADDER: { pullPlayerState.ladderDir = moveDir; pullPlayerState.ladderTime = gameLocal.time; #if 0 // test ladder physics code if ( !player->GetPlayerPhysics().IsGrounded() ) { trace_t trace; bool onLadder = false; if ( gameLocal.clip.Translation( CLIP_DEBUG_PARMS_CLIENTINFO( self ) trace, org, org + horizontalDir * 32.0f, NULL, mat3_identity, MASK_PLAYERSOLID, player ) ) { onLadder = ( gameLocal.entities[ trace.c.entityNum ]->Cast< sdLadderEntity >() != NULL ); } if ( onLadder && !player->GetPlayerPhysics().OnLadder() ) { usercmd.forwardmove = 0; } } #endif break; } } if ( player->GetPlayerPhysics().OnLadder() || pullPlayerState.ladderTime > gameLocal.time - 500 ) { moveDir = pullPlayerState.ladderDir; } idAngles viewAngles = moveDir.ToAngles(); player->Move( usercmd, viewAngles ); return true; }
/* ============ idAASLocal::ShowArea ============ */ void idAASLocal::ShowArea( const idVec3 &origin, int mode ) const { static int lastAreaNum; int areaNum; const aasArea_t *area; idVec3 org; org = origin; if ( mode == 1 ) { areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), AAS_AREA_REACHABLE_WALK, TravelFlagInvalidForTeam() ); PushPointIntoArea( areaNum, org ); } else { areaNum = PointAreaNum( origin ); } if ( aas_showTravelTime.GetInteger() ) { int travelTime; const aasReachability_t *reach; RouteToGoalArea( areaNum, org, aas_showTravelTime.GetInteger(), TFL_WALK|TFL_AIR, travelTime, &reach ); gameLocal.Printf( "\rtt = %4d", travelTime ); if ( reach ) { gameLocal.Printf( " to area %4d", reach->toAreaNum ); DrawArea( reach->toAreaNum ); } } if ( areaNum != lastAreaNum ) { area = &file->GetArea( areaNum ); gameLocal.Printf( "area %d:", areaNum ); if ( area->flags & AAS_AREA_LEDGE ) { gameLocal.Printf( " ledge" ); } if ( area->flags & AAS_AREA_CONTENTS_CLUSTERPORTAL ) { gameLocal.Printf( " clusterportal" ); } if ( area->flags & AAS_AREA_CONTENTS_OBSTACLE ) { gameLocal.Printf( " obstacle" ); } if ( area->flags & AAS_AREA_OUTSIDE ) { gameLocal.Printf( " outside" ); } if ( area->flags & AAS_AREA_HIGH_CEILING ) { gameLocal.Printf( " highceiling" ); } if ( area->travelFlags & ( TFL_INVALID | TFL_INVALID_GDF | TFL_INVALID_STROGG ) ) { gameLocal.Printf( " /" ); if ( area->travelFlags & TFL_INVALID ) { gameLocal.Printf( " invalid" ); } if ( area->travelFlags & TFL_INVALID_GDF ) { gameLocal.Printf( " invalidgdf" ); } if ( area->travelFlags & TFL_INVALID_STROGG ) { gameLocal.Printf( " invalidstrogg" ); } } gameLocal.Printf( "\n" ); lastAreaNum = areaNum; } if ( org != origin ) { idBounds bnds = file->GetSettings().boundingBox; bnds[ 1 ].z = bnds[ 0 ].z; gameRenderWorld->DebugBounds( colorYellow, bnds, org ); gameRenderWorld->DebugArrow( colorYellow, origin, org, 1 ); } DrawArea( areaNum ); }