Files
RTCW-MP/src/botlib/be_aas_routealt.c

272 lines
8.9 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
===========================================================================
Return to Castle Wolfenstein multiplayer GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”).
RTCW MP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW MP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_routealt.c
*
* desc: AAS
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_utils.h"
#include "l_memory.h"
#include "l_log.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
//#define ENABLE_ALTROUTING
typedef struct midrangearea_s
{
int valid;
unsigned short starttime;
unsigned short goaltime;
} midrangearea_t;
midrangearea_t *midrangeareas;
int *clusterareas;
int numclusterareas;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_AltRoutingFloodCluster_r( int areanum ) {
int i, otherareanum;
aas_area_t *area;
aas_face_t *face;
//add the current area to the areas of the current cluster
clusterareas[numclusterareas] = areanum;
numclusterareas++;
//remove the area from the mid range areas
midrangeareas[areanum].valid = qfalse;
//flood to other areas through the faces of this area
area = &( *aasworld ).areas[areanum];
for ( i = 0; i < area->numfaces; i++ )
{
face = &( *aasworld ).faces[abs( ( *aasworld ).faceindex[area->firstface + i] )];
//get the area at the other side of the face
if ( face->frontarea == areanum ) {
otherareanum = face->backarea;
} else { otherareanum = face->frontarea;}
//if there is an area at the other side of this face
if ( !otherareanum ) {
continue;
}
//if the other area is not a midrange area
if ( !midrangeareas[otherareanum].valid ) {
continue;
}
//
AAS_AltRoutingFloodCluster_r( otherareanum );
} //end for
} //end of the function AAS_AltRoutingFloodCluster_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_AlternativeRouteGoals( vec3_t start, vec3_t goal, int travelflags,
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
int color ) {
#ifndef ENABLE_ALTROUTING
return 0;
#else
int i, j, startareanum, goalareanum, bestareanum;
int numaltroutegoals, nummidrangeareas;
int starttime, goaltime, goaltraveltime;
float dist, bestdist;
vec3_t mid, dir;
#ifdef DEBUG
int startmillisecs;
startmillisecs = Sys_MilliSeconds();
#endif
startareanum = AAS_PointAreaNum( start );
if ( !startareanum ) {
return 0;
}
goalareanum = AAS_PointAreaNum( goal );
if ( !goalareanum ) {
return 0;
}
//travel time towards the goal area
goaltraveltime = AAS_AreaTravelTimeToGoalArea( startareanum, start, goalareanum, travelflags );
//clear the midrange areas
memset( midrangeareas, 0, ( *aasworld ).numareas * sizeof( midrangearea_t ) );
numaltroutegoals = 0;
//
nummidrangeareas = 0;
//
for ( i = 1; i < ( *aasworld ).numareas; i++ )
{
//
if ( !( ( *aasworld ).areasettings[i].contents & AREACONTENTS_ROUTEPORTAL ) ) {
continue;
}
//if the area has no reachabilities
if ( !AAS_AreaReachability( i ) ) {
continue;
}
//tavel time from the area to the start area
starttime = AAS_AreaTravelTimeToGoalArea( startareanum, start, i, travelflags );
if ( !starttime ) {
continue;
}
//if the travel time from the start to the area is greater than the shortest goal travel time
if ( starttime > 1.5 * goaltraveltime ) {
continue;
}
//travel time from the area to the goal area
goaltime = AAS_AreaTravelTimeToGoalArea( i, NULL, goalareanum, travelflags );
if ( !goaltime ) {
continue;
}
//if the travel time from the area to the goal is greater than the shortest goal travel time
if ( goaltime > 1.5 * goaltraveltime ) {
continue;
}
//this is a mid range area
midrangeareas[i].valid = qtrue;
midrangeareas[i].starttime = starttime;
midrangeareas[i].goaltime = goaltime;
Log_Write( "%d midrange area %d", nummidrangeareas, i );
nummidrangeareas++;
} //end for
//
for ( i = 1; i < ( *aasworld ).numareas; i++ )
{
if ( !midrangeareas[i].valid ) {
continue;
}
//get the areas in one cluster
numclusterareas = 0;
AAS_AltRoutingFloodCluster_r( i );
//now we've got a cluster with areas through which an alternative route could go
//get the 'center' of the cluster
VectorClear( mid );
for ( j = 0; j < numclusterareas; j++ )
{
VectorAdd( mid, ( *aasworld ).areas[clusterareas[j]].center, mid );
} //end for
VectorScale( mid, 1.0 / numclusterareas, mid );
//get the area closest to the center of the cluster
bestdist = 999999;
bestareanum = 0;
for ( j = 0; j < numclusterareas; j++ )
{
VectorSubtract( mid, ( *aasworld ).areas[clusterareas[j]].center, dir );
dist = VectorLength( dir );
if ( dist < bestdist ) {
bestdist = dist;
bestareanum = clusterareas[j];
} //end if
} //end for
//now we've got an area for an alternative route
//FIXME: add alternative goal origin
VectorCopy( ( *aasworld ).areas[bestareanum].center, altroutegoals[numaltroutegoals].origin );
altroutegoals[numaltroutegoals].areanum = bestareanum;
altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime;
altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime;
altroutegoals[numaltroutegoals].extratraveltime =
( midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime ) -
goaltraveltime;
numaltroutegoals++;
//
#ifdef DEBUG
botimport.Print( PRT_MESSAGE, "alternative route goal area %d, numclusterareas = %d\n", bestareanum, numclusterareas );
if ( color ) {
AAS_DrawPermanentCross( ( *aasworld ).areas[bestareanum].center, 10, color );
} //end if
//AAS_ShowArea(bestarea, qtrue);
#endif
//don't return more than the maximum alternative route goals
if ( numaltroutegoals >= maxaltroutegoals ) {
break;
}
} //end for
botimport.Print( PRT_MESSAGE, "%d alternative route goals\n", numaltroutegoals );
#ifdef DEBUG
botimport.Print( PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs );
#endif
return numaltroutegoals;
#endif
} //end of the function AAS_AlternativeRouteGoals
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_InitAlternativeRouting( void ) {
#ifdef ENABLE_ALTROUTING
if ( midrangeareas ) {
FreeMemory( midrangeareas );
}
midrangeareas = (midrangearea_t *) GetMemory( ( *aasworld ).numareas * sizeof( midrangearea_t ) );
if ( clusterareas ) {
FreeMemory( clusterareas );
}
clusterareas = (int *) GetMemory( aasworld.numareas * sizeof( int ) );
#endif
} //end of the function AAS_InitAlternativeRouting
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShutdownAlternativeRouting( void ) {
#ifdef ENABLE_ALTROUTING
if ( midrangeareas ) {
FreeMemory( midrangeareas );
}
midrangeareas = NULL;
if ( clusterareas ) {
FreeMemory( clusterareas );
}
clusterareas = NULL;
numclusterareas = 0;
#endif
}