Initial commit.
This commit is contained in:
480
code/RMG/RM_Area.cpp
Normal file
480
code/RMG/RM_Area.cpp
Normal file
@@ -0,0 +1,480 @@
|
||||
/************************************************************************************************
|
||||
*
|
||||
* Copyright (C) 2001-2002 Raven Software
|
||||
*
|
||||
* RM_Area.cpp
|
||||
*
|
||||
************************************************************************************************/
|
||||
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
#include "rm_headers.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma optimize("p", on)
|
||||
#endif
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMArea::CRMArea
|
||||
* constructor
|
||||
*
|
||||
* inputs:
|
||||
* none
|
||||
*
|
||||
* return:
|
||||
* none
|
||||
*
|
||||
************************************************************************************************/
|
||||
CRMArea::CRMArea (
|
||||
float spacingRadius,
|
||||
float paddingSize,
|
||||
float confineRadius,
|
||||
vec3_t confineOrigin,
|
||||
vec3_t lookAtOrigin,
|
||||
bool flatten,
|
||||
int symmetric
|
||||
)
|
||||
{
|
||||
mMoveCount = 0;
|
||||
mAngle = 0;
|
||||
mCollision = true;
|
||||
mConfineRadius = confineRadius;
|
||||
mPaddingSize = paddingSize;
|
||||
mSpacingRadius = spacingRadius;
|
||||
mFlatten = flatten;
|
||||
mLookAt = true;
|
||||
mLockOrigin = false;
|
||||
mSymmetric = symmetric;
|
||||
mRadius = spacingRadius;
|
||||
|
||||
VectorCopy ( confineOrigin, mConfineOrigin );
|
||||
VectorCopy ( lookAtOrigin, mLookAtOrigin );
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMArea::LookAt
|
||||
* Angle the area towards the given point
|
||||
*
|
||||
* inputs:
|
||||
* lookat - the origin to look at
|
||||
*
|
||||
* return:
|
||||
* the angle in radians that was calculated
|
||||
*
|
||||
************************************************************************************************/
|
||||
float CRMArea::LookAt ( vec3_t lookat )
|
||||
{
|
||||
if (mLookAt)
|
||||
{ // this area orients itself towards a point
|
||||
vec3_t a;
|
||||
|
||||
VectorCopy ( lookat, mLookAtOrigin );
|
||||
VectorSubtract ( lookat, mOrigin, a );
|
||||
|
||||
mAngle = atan2 ( a[1], a[0] );
|
||||
}
|
||||
|
||||
return mAngle;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMArea::Mirror
|
||||
* Mirrors the area to the other side of the map. This includes mirroring the confine origin
|
||||
* and lookat origin
|
||||
*
|
||||
* inputs:
|
||||
* none
|
||||
*
|
||||
* return:
|
||||
* none
|
||||
*
|
||||
************************************************************************************************/
|
||||
void CRMArea::Mirror ( void )
|
||||
{
|
||||
mOrigin[0] = -mOrigin[0];
|
||||
mOrigin[1] = -mOrigin[1];
|
||||
|
||||
mConfineOrigin[0] = -mConfineOrigin[0];
|
||||
mConfineOrigin[1] = -mConfineOrigin[1];
|
||||
|
||||
mLookAtOrigin[0] = -mLookAtOrigin[0];
|
||||
mLookAtOrigin[1] = -mLookAtOrigin[1];
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMAreaManager::CRMAreaManager
|
||||
* constructor
|
||||
*
|
||||
* inputs:
|
||||
* none
|
||||
*
|
||||
* return:
|
||||
* none
|
||||
*
|
||||
************************************************************************************************/
|
||||
CRMAreaManager::CRMAreaManager ( const vec3_t mins, const vec3_t maxs)
|
||||
{
|
||||
VectorCopy ( mins, mMins );
|
||||
VectorCopy ( maxs, mMaxs );
|
||||
|
||||
mWidth = mMaxs[0] - mMins[0];
|
||||
mHeight = mMaxs[1] - mMins[1];
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMAreaManager::~CRMAreaManager
|
||||
* Removes all managed areas
|
||||
*
|
||||
* inputs:
|
||||
* none
|
||||
*
|
||||
* return:
|
||||
* none
|
||||
*
|
||||
************************************************************************************************/
|
||||
CRMAreaManager::~CRMAreaManager ( )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = mAreas.size() - 1; i >=0; i -- )
|
||||
{
|
||||
delete mAreas[i];
|
||||
}
|
||||
|
||||
mAreas.clear();
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMAreaManager::MoveArea
|
||||
* Moves an area within the area manager thus shifting any other areas as needed
|
||||
*
|
||||
* inputs:
|
||||
* area - area to be moved
|
||||
* origin - new origin to attempt to move to
|
||||
*
|
||||
* return:
|
||||
* none
|
||||
*
|
||||
************************************************************************************************/
|
||||
void CRMAreaManager::MoveArea ( CRMArea* movedArea, vec3_t origin)
|
||||
{
|
||||
int index;
|
||||
int size;
|
||||
|
||||
// Increment the addcount (this is for infinite protection)
|
||||
movedArea->AddMoveCount ();
|
||||
|
||||
// Infinite recursion prevention
|
||||
if ( movedArea->GetMoveCount() > 250 )
|
||||
{
|
||||
// assert ( 0 );
|
||||
movedArea->EnableCollision ( false );
|
||||
return;
|
||||
}
|
||||
|
||||
// First set the area's origin, This may cause it to be in collision with
|
||||
// another area but that will get fixed later
|
||||
movedArea->SetOrigin ( origin );
|
||||
|
||||
// when symmetric we want to ensure that no instances end up on the "other" side of the imaginary diaganol that cuts the map in two
|
||||
// mSymmetric tells us which side of the map is legal
|
||||
if ( movedArea->GetSymmetric ( ) )
|
||||
{
|
||||
const vec3pair_t& bounds = TheRandomMissionManager->GetLandScape()->GetBounds();
|
||||
|
||||
vec3_t point;
|
||||
vec3_t dir;
|
||||
vec3_t tang;
|
||||
bool push;
|
||||
float len;
|
||||
|
||||
VectorSubtract( movedArea->GetOrigin(), bounds[0], point );
|
||||
VectorSubtract( bounds[1], bounds[0], dir );
|
||||
VectorNormalize(dir);
|
||||
|
||||
dir[2] = 0;
|
||||
point[2] = 0;
|
||||
VectorMA( bounds[0], DotProduct(point, dir), dir, tang );
|
||||
VectorSubtract ( movedArea->GetOrigin(), tang, dir );
|
||||
|
||||
dir[2] = 0;
|
||||
push = false;
|
||||
len = VectorNormalize(dir);
|
||||
|
||||
if ( len < movedArea->GetRadius ( ) )
|
||||
{
|
||||
if ( movedArea->GetLockOrigin ( ) )
|
||||
{
|
||||
movedArea->EnableCollision ( false );
|
||||
return;
|
||||
}
|
||||
|
||||
VectorMA ( point, (movedArea->GetSpacingRadius() - len) + TheRandomMissionManager->GetLandScape()->irand(10,movedArea->GetSpacingRadius()), dir, point );
|
||||
origin[0] = point[0] + bounds[0][0];
|
||||
origin[1] = point[1] + bounds[0][1];
|
||||
movedArea->SetOrigin ( origin );
|
||||
}
|
||||
|
||||
switch ( movedArea->GetSymmetric ( ) )
|
||||
{
|
||||
case SYMMETRY_TOPLEFT:
|
||||
if ( origin[1] > origin[0] )
|
||||
{
|
||||
movedArea->Mirror ( );
|
||||
}
|
||||
break;
|
||||
|
||||
case SYMMETRY_BOTTOMRIGHT:
|
||||
if ( origin[1] < origin[0] )
|
||||
{
|
||||
movedArea->Mirror ( );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// unknown symmetry type
|
||||
assert ( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Confine to area unless we are being pushed back by the same guy who pushed us last time (infinite loop)
|
||||
if ( movedArea->GetConfineRadius() )
|
||||
{
|
||||
if ( movedArea->GetMoveCount() < 25 )
|
||||
{
|
||||
vec3_t cdiff;
|
||||
float cdist;
|
||||
|
||||
VectorSubtract ( movedArea->GetOrigin(), movedArea->GetConfineOrigin(), cdiff );
|
||||
cdiff[2] = 0;
|
||||
cdist = VectorLength ( cdiff );
|
||||
|
||||
if ( cdist + movedArea->GetSpacingRadius() > movedArea->GetConfineRadius() )
|
||||
{
|
||||
cdist = movedArea->GetConfineRadius() - movedArea->GetSpacingRadius();
|
||||
VectorNormalize ( cdiff );
|
||||
|
||||
VectorMA ( movedArea->GetConfineOrigin(), cdist, cdiff, movedArea->GetOrigin());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// See if it fell off the world in the x direction
|
||||
if ( movedArea->GetOrigin()[0] + movedArea->GetSpacingRadius() > mMaxs[0] )
|
||||
movedArea->GetOrigin()[0] = mMaxs[0] - movedArea->GetSpacingRadius() - (TheRandomMissionManager->GetLandScape()->irand(10,200));
|
||||
else if ( movedArea->GetOrigin()[0] - movedArea->GetSpacingRadius() < mMins[0] )
|
||||
movedArea->GetOrigin()[0] = mMins[0] + movedArea->GetSpacingRadius() + (TheRandomMissionManager->GetLandScape()->irand(10,200));
|
||||
|
||||
// See if it fell off the world in the y direction
|
||||
if ( movedArea->GetOrigin()[1] + movedArea->GetSpacingRadius() > mMaxs[1] )
|
||||
movedArea->GetOrigin()[1] = mMaxs[1] - movedArea->GetSpacingRadius() - (TheRandomMissionManager->GetLandScape()->irand(10,200));
|
||||
else if ( movedArea->GetOrigin()[1] - movedArea->GetSpacingRadius() < mMins[1] )
|
||||
movedArea->GetOrigin()[1] = mMins[1] + movedArea->GetSpacingRadius() + (TheRandomMissionManager->GetLandScape()->irand(10,200));
|
||||
|
||||
// Look at what we need to look at
|
||||
movedArea->LookAt ( movedArea->GetLookAtOrigin() );
|
||||
|
||||
// Dont collide against things that have no collision
|
||||
// if ( !movedArea->IsCollisionEnabled ( ) )
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// See if its colliding
|
||||
for(index = 0, size = mAreas.size(); index < size; index ++ )
|
||||
{
|
||||
CRMArea *area = mAreas[index];
|
||||
vec3_t diff;
|
||||
vec3_t newOrigin;
|
||||
float dist;
|
||||
float targetdist;
|
||||
|
||||
// Skip the one that was moved in the first place
|
||||
if ( area == movedArea )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( area->GetLockOrigin ( ) && movedArea->GetLockOrigin( ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Dont collide against things that have no collision
|
||||
if ( !area->IsCollisionEnabled ( ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Grab the distance between the two
|
||||
// only want the horizontal distance -- dmv
|
||||
//dist = Distance ( movedArea->GetOrigin ( ), area->GetOrigin ( ));
|
||||
vec3_t maOrigin;
|
||||
vec3_t aOrigin;
|
||||
VectorCopy(movedArea->GetOrigin(), maOrigin);
|
||||
VectorCopy(area->GetOrigin(), aOrigin);
|
||||
maOrigin[2] = aOrigin[2] = 0;
|
||||
dist = Distance ( maOrigin, aOrigin );
|
||||
targetdist = movedArea->GetSpacingRadius() + area->GetSpacingRadius() + maximum(movedArea->GetPaddingSize(),area->GetPaddingSize());
|
||||
|
||||
if ( dist == 0 )
|
||||
{
|
||||
area->GetOrigin()[0] += (50 * (float)(TheRandomMissionManager->GetLandScape()->irand(0,99))/100.0f);
|
||||
area->GetOrigin()[1] += (50 * (float)(TheRandomMissionManager->GetLandScape()->irand(0,99))/100.0f);
|
||||
|
||||
VectorCopy(area->GetOrigin(), aOrigin);
|
||||
aOrigin[2] = 0;
|
||||
|
||||
dist = Distance ( maOrigin, aOrigin );
|
||||
}
|
||||
|
||||
// Are they are enough apart?
|
||||
if ( dist >= targetdist )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Dont move a step if locked
|
||||
if ( area->GetLockOrigin ( ) )
|
||||
{
|
||||
MoveArea ( area, area->GetOrigin ( ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
// we got a collision, move the guy we hit
|
||||
VectorSubtract ( area->GetOrigin(), movedArea->GetOrigin(), diff );
|
||||
diff[2] = 0;
|
||||
VectorNormalize ( diff );
|
||||
|
||||
// Push by the difference in the distance and no-collide radius
|
||||
VectorMA ( area->GetOrigin(), targetdist - dist + 1 , diff, newOrigin );
|
||||
|
||||
// Move the area now
|
||||
MoveArea ( area, newOrigin );
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMAreaManager::CreateArea
|
||||
* Creates an area and adds it to the list of managed areas
|
||||
*
|
||||
* inputs:
|
||||
* none
|
||||
*
|
||||
* return:
|
||||
* a pointer to the newly added area class
|
||||
*
|
||||
************************************************************************************************/
|
||||
CRMArea* CRMAreaManager::CreateArea (
|
||||
vec3_t origin,
|
||||
float spacingRadius,
|
||||
int spacingLine,
|
||||
float paddingSize,
|
||||
float confineRadius,
|
||||
vec3_t confineOrigin,
|
||||
vec3_t lookAtOrigin,
|
||||
bool flatten,
|
||||
bool collide,
|
||||
bool lockorigin,
|
||||
int symmetric
|
||||
)
|
||||
{
|
||||
CRMArea* area = new CRMArea ( spacingRadius, paddingSize, confineRadius, confineOrigin, lookAtOrigin, flatten, symmetric );
|
||||
|
||||
if ( lockorigin || spacingLine )
|
||||
{
|
||||
area->LockOrigin ( );
|
||||
}
|
||||
|
||||
if (origin[0] != lookAtOrigin[0] || origin[1] != lookAtOrigin[1])
|
||||
area->EnableLookAt(true);
|
||||
|
||||
// First add the area to the list
|
||||
mAreas.push_back ( area );
|
||||
|
||||
area->EnableCollision(collide);
|
||||
|
||||
// Set the real radius which is used for center line detection
|
||||
if ( spacingLine )
|
||||
{
|
||||
area->SetRadius ( spacingRadius + (spacingLine - 1) * spacingRadius );
|
||||
}
|
||||
|
||||
// Now move the area around
|
||||
MoveArea ( area, origin );
|
||||
|
||||
if ( (origin[0] != lookAtOrigin[0] || origin[1] != lookAtOrigin[1]) )
|
||||
{
|
||||
int i;
|
||||
vec3_t linedir;
|
||||
vec3_t dir;
|
||||
vec3_t up = {0,0,1};
|
||||
vec3_t zerodvec;
|
||||
|
||||
VectorClear(zerodvec);
|
||||
|
||||
VectorSubtract ( lookAtOrigin, origin, dir );
|
||||
VectorNormalize ( dir );
|
||||
dir[2] = 0;
|
||||
CrossProduct ( dir, up, linedir );
|
||||
|
||||
for ( i = 0; i < spacingLine - 1; i ++ )
|
||||
{
|
||||
CRMArea* linearea;
|
||||
vec3_t lineorigin;
|
||||
|
||||
linearea = new CRMArea ( spacingRadius, paddingSize, 0, zerodvec, zerodvec, false, symmetric );
|
||||
linearea->LockOrigin ( );
|
||||
linearea->EnableCollision(collide);
|
||||
|
||||
VectorMA ( origin, spacingRadius + (spacingRadius * 2 * i), linedir, lineorigin );
|
||||
mAreas.push_back ( linearea );
|
||||
MoveArea ( linearea, lineorigin );
|
||||
|
||||
linearea = new CRMArea ( spacingRadius, paddingSize, 0, zerodvec, zerodvec, false, symmetric );
|
||||
linearea->LockOrigin ( );
|
||||
linearea->EnableCollision(collide);
|
||||
|
||||
VectorMA ( origin, -spacingRadius - (spacingRadius * 2 * i), linedir, lineorigin );
|
||||
mAreas.push_back ( linearea );
|
||||
MoveArea ( linearea, lineorigin );
|
||||
}
|
||||
}
|
||||
|
||||
// Return it for convienience
|
||||
return area;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* CRMAreaManager::EnumArea
|
||||
* Allows for enumeration through the area list. If an invalid index is given then NULL will
|
||||
* be returned;
|
||||
*
|
||||
* inputs:
|
||||
* index - current enumeration index
|
||||
*
|
||||
* return:
|
||||
* requested area class pointer or NULL if the index was invalid
|
||||
*
|
||||
************************************************************************************************/
|
||||
CRMArea* CRMAreaManager::EnumArea ( const int index )
|
||||
{
|
||||
// This isnt an assertion case because there is no size method for
|
||||
// the area manager so the areas are enumerated until NULL is returned.
|
||||
if ( index < 0 || index >= mAreas.size ( ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mAreas[index];
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma optimize("p", off)
|
||||
#endif
|
||||
Reference in New Issue
Block a user