/* ============ idAASLocal::ShowWalkPath ============ */ void idAASLocal::ShowWalkPath( 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_WALK ); PushPointIntoAreaNum( areaNum, org ); curAreaNum = areaNum; for( i = 0; i < 100; i++ ) { if( !RouteToGoalArea( curAreaNum, org, goalAreaNum, TFL_WALK | TFL_AIR, travelTime, &reach ) ) { break; } if( !reach ) { break; } gameRenderWorld->DebugArrow( colorGreen, org, reach->start, 2 ); DrawReachability( reach ); if( reach->toAreaNum == goalAreaNum ) { break; } curAreaNum = reach->toAreaNum; org = reach->end; } if( WalkPathToGoal( path, areaNum, origin, goalAreaNum, goalOrigin, TFL_WALK | 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::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::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; }